# 錯誤與契約

查閱 HTTP error response、唯讀邊界，以及搜尋 response 保證提供的欄位。

## Error response

| 條件 | HTTP status | Body 範例 |
|---|---|---|
| 缺少 `db` | 400 | `{"error":"db is required"}` |
| 未知或未載入的 `db` | 400 | `{"error":"\"name\" not exist"}` |
| 缺少或空白的 `q` | 400 | `{"error":"invalid argument: q is required"}` |
| 未知 `target` | 400 | `{"error":"invalid argument: unknown target \"bogus\""}` |
| Search、embedding 或 registry failure | 500 | `{"error":"..."}` |
| `remote` 關閉時存取 `/mcp` | 404 | Gin 預設 not-found body |

`db` 檢查在 router middleware 內、search handler 之前執行。其他 argument error 都包裝為 `search.ErrInvalidArgument`，由 handler 對應到 400；其餘一律為 500。若並行 search branch 任一失敗，request 會回傳 error，而不是 partial result。

## 唯讀邊界

Router 不暴露任何內容寫入 route；`/mcp` 僅接受 protocol transport 所需的 HTTP method，背後兩個 tool 皆為唯讀。若要新增內容，請將檔案放入已註冊 inbox，讓 watcher-controlled indexing pipeline 寫入 SQLite；見 [索引管線](/zh/indexing-pipeline)。

## API response 契約

搜尋結果會依 source 以首次出現的順序分組，且只暴露：

```json
{
  "source": "/path/to/file.md",
  "matches": [
    {"chunk": 1, "content": "..."}
  ]
}
```

| Field | 意義 |
|---|---|
| `source` | 已索引檔案在資料庫 inbox 內的絕對路徑（`~/.config/kuradb/<db>/inbox/...`），而非 `~/Kura_<db>` symlink 路徑 |
| `matches[].chunk` | 該檔案內的 chunk 編號 |
| `matches[].content` | Chunk 文字 |

Row ID、semantic score、keyword hit count、chunk total 與 cache state 等內部欄位仍屬 implementation detail，永遠不會序列化。Consumer 應依賴結果順序，而非 score。
