Errors and Contract
Read the HTTP error responses, the read-only boundary, and the fields the search response guarantees.
Error responses
| Condition | HTTP status | Example body |
|---|---|---|
Missing db |
400 | {"error":"db is required"} |
Unknown or unloaded db |
400 | {"error":"\"name\" not exist"} |
Missing or empty q |
400 | {"error":"invalid argument: q is required"} |
Unknown target |
400 | {"error":"invalid argument: unknown target \"bogus\""} |
| Search, embedding, or registry failure | 500 | {"error":"..."} |
/mcp while remote is disabled |
404 | Gin default not-found body |
The db checks run in router middleware before the search handler. Every other argument error is wrapped in search.ErrInvalidArgument, which the handler maps to 400; anything else becomes 500. If either concurrent search branch fails, the request returns an error rather than a partial result.
Read-only boundary
The router exposes no mutation routes. /mcp accepts the HTTP methods the protocol transport requires, but the two tools behind it are read-only. To add content, place files in a registered inbox and let the watcher-controlled indexing pipeline write to SQLite; see Indexing Pipeline.
API response contract
Search results are grouped by source in first-seen order and expose only:
{
"source": "/path/to/file.md",
"matches": [
{"chunk": 1, "content": "..."}
]
}
| Field | Meaning |
|---|---|
source |
Absolute path of the indexed file inside the database inbox (~/.config/kuradb/<db>/inbox/...), not the ~/Kura_<db> symlink path |
matches[].chunk |
Chunk index within that file |
matches[].content |
Chunk text |
Internal fields such as row ID, semantic score, keyword hit count, chunk total, and cache state remain implementation details and are never serialized. Consumers should rely on result order, not on a score.