Brain
Errors and rate limits
The Unison error envelope, every error code with its HTTP status, optimistic-concurrency conflicts, and how to handle 429s.
Every error is the same envelope:
{ "error": { "code": "snake_case", "message": "…" } }Codes
| Code | HTTP | Meaning |
|---|---|---|
invalid_path | 400 | malformed path or not ending in .md |
invalid_json | 400 | request body is not valid JSON |
invalid_request | 400 | auth endpoints - missing or invalid fields |
bad_request | 400 | other validation failures |
unauthenticated | 401 | missing/invalid usk_ token |
unauthorized | 401 | internal auth mapping only - rare |
forbidden | 403 | token lacks the required scope, or write to a read-only path (/system/ or the ingest-only /private/sources/) |
not_found | 404 | e.g. GET /v1/brain/doc for a missing path |
conflict | 409 | content-hash mismatch on write, or email_registered on provision |
precondition_failed | 412 | a precondition on the request was not met |
payload_too_large | 413 | request body exceeds the size limit |
unprocessable_content | 422 | request is well-formed but semantically invalid |
rate_limited / too_many_requests | 429 | per-token limit - retry with backoff |
rest_error | 500 | generic internal server error |
Optimistic concurrency
PUT /v1/brain/doc accepts expectedContentHash (hex16). If the document changed since you read it, the write returns 409 conflict instead of clobbering - re-read, re-apply, retry. CLI: unison write --if-match <hash>.
Rate limiting
Limits are per token. On 429 rate_limited, back off and retry; for high-volume ingest prefer batching (up to 100 items per POST /v1/brain/ingest) over per-item calls.
Client behavior
Clients (SDK/CLI/MCP) never pre-check scopes or validate paths - they send the call and surface the server's verdict. Treat every 4xx as authoritative.