Skip to content

Errors

Every error response uses one envelope:

{ "error": "branch not found: staging", "code": "branch_not_found" }

error is the human-readable message; code is the stable machine-readable identifier your client branches on. The set of codes is small and deliberately stable — a new one is added only when a client can act differently on it, so it’s safe to switch on.

Both SDKs surface the code directly: MemoturnError.code in TypeScript and Python. The CLI prints an actionable hint on stderr keyed on the same codes.

codestatusmeaning — and what to do
unauthorized401No or invalid credential. Set MEMOTURN_TOKEN (mint one with memoturn token create) or MEMOTURN_PLATFORM_KEY.
forbidden403The credential is valid but doesn’t cover this database, profile, or scope — check which token you’re holding.
not_found404Generic lookup miss (memory id, KV key, erasure id).
database_not_found404The database doesn’t exist. memoturn db list / memoturn db create <name>.
branch_not_found404The branch doesn’t exist on this database. memoturn branch list <db>.
already_exists409Create of a database/branch that already exists. Treat as success or pick another name.
conflict409A concurrent change won (manifest CAS, rewind target, tighten-only policy violation). Re-read, then retry.
invalid_request400Malformed body, bad SQL, unsupported filter. Fix the request; don’t retry as-is.
payload_too_large413Body exceeds the limit (default 32 MiB for writes). Split the batch.
request_timeout408The request exceeded MEMOTURN_REQUEST_TIMEOUT (default 30 s).
overloaded429Backpressure: the per-database write queue or control rate limit shed the request. Honor Retry-After.
unconfigured503An AI opt-in (assistant, extraction, embedding) is not configured on this node. Fall back to the bring-your-own path — e.g. use /recall and synthesize the answer yourself.
unavailable503The control plane (writer leases, policy store) is unreachable. Retry with backoff.
internal500/502Unexpected failure, or an error forwarding to the owner node.

408 (request timeout) and 413 (payload too large) are emitted by middleware before the handler runs, with empty or plain-text bodies — no envelope. Both SDKs derive the code from the status for these, so MemoturnError.code is still request_timeout / payload_too_large; if you’re calling the API raw, fall back to the status code.

When concurrent writes to one database exceed MEMOTURN_WRITE_QUEUE_DEPTH (default 256), or a control endpoint exceeds its rate budget, the node sheds the request with 429 and a Retry-After header (seconds). The TypeScript SDK retries these automatically with backoff; elsewhere, wait the indicated interval before retrying. See scaling for how group commit absorbs write bursts before shedding starts.

The full envelope schema, including the code enum, is part of the OpenAPI spec.