CortexDB Docs
API Reference

Error codes

The error body, how to tell a retriable error, and every error code the v1 API returns, with the page that explains each.

The error body

Most errors are JSON with a flat body:

{
  "error_code": "INVALID_BODY",
  "message": "invalid experience body at `scope`: segment 0 is missing ':' delimiter …",
  "retriable": false,
  "request_id": "req_01a0e828-…",
  "details": { "field_path": "scope", "reason": "…", "schema": "/v1/schemas/experience_envelope" }
}
  • error_code is UPPERCASE with underscores, with one exception: a multipart upload to /v1/blobs answers 415 unsupported_media_type in lowercase.
  • retriable is the rule to follow: true means send the identical request again (the same idempotency_key is safe); false means change the request first. The newer 409/503 refusals also send a Retry-After header.
  • request_id is on most errors but not all: the forget, erasure, scope, usage and re-derivation routes omit it. The response header x-request-id is always present; log that one. Send your own X-Request-Id and a successful response echoes it. An error whose body carries a request_id minted that id itself and also returns it in a header: x-request-id (for example a 404 from GET /v1/events/{id}), or x-cortex-request-id on a 401, whose x-request-id still echoes yours. Since v0.10.2 the same id is on the request's log line and on the audit rows it writes.
  • details is present only when the error has any (for example INVALID_BODY, IDEMPOTENCY_CONFLICT, ENRICHMENT_OFF, SETTLEMENT_UNAVAILABLE, BLOB_TEXT_ENCODING_UNKNOWN).

Some validation errors are plain text

When the body or query string cannot be parsed into the route's type, some routes answer with a plain-text message, not the JSON body: an unknown field on /v1/forget (422 Failed to deserialize the JSON body …: unknown field …), a value of the wrong type (facet_plan_override: "x" on /v1/answer), or a missing required query parameter (GET /v1/events without scope → 400 Failed to deserialize query string: missing field scope). Other routes, such as /v1/recall and /v1/experience, wrap the same kind of mistake in a JSON INVALID_BODY. Clients should handle a non-JSON error body.

Codes by area

Writes and captures

StatusCodeWhenRetriable
422INVALID_BODYA malformed body or field (bad scope, bad ?wait= value, unknown recall field); also a field whose capability this server does not list (details.unsupported_fields and details.required_capabilities)no
422INVALID_ENVELOPEA malformed language, scripts, context.timezone, context.refers_to, or an idempotency_key over 64 charactersno
422UNREGISTERED_SCOPE_TYPEA scope type not in the allowed set (e.g. channel:) on the first write into a new scopeno
409IDEMPOTENCY_CONFLICTThe same idempotency_key in the same scope with a different bodyno
422BLOB_TEXT_ENCODING_UNKNOWNA blob_ref to a text blob whose bytes decode in no declared or detectable encodingno
503SETTLEMENT_UNAVAILABLE?wait=settled on the default single-node serverno
409DESTRUCTIVE_OPERATION_IN_PROGRESSA capture that would register a new scope inside a running forget or erasure, after CORTEX_DESTRUCTIVE_LEASE_WAIT_SECSyes (Retry-After: 5)
502INDEXING_FAILEDAccepted into the WAL but indexing failed; re-send with the same keyyes
408WAIT_TIMEOUTA ?wait=indexed or consolidated capture ran out of its one wait budget (about 30 s; bulk min(30 s + 1 s per item, 600 s)); the write is captured and durable. details has waited_ms, waiting_on and status_url (single) or event_ids (bulk)yes: poll, or re-send with the same idempotency_key

Details: Experience.

Reads, recall and answers

StatusCodeWhenRetriable
404NOT_FOUNDAn unknown, forgotten, erased or cancelled id (GET /v1/events/{id}, erasure jobs, retention policies); also an event outside GET /v1/events/{id}?scope=no
422INVALID_SCOPE_GRAMMARAn empty, blank or malformed ?scope= on GET /v1/events/{id} (a repeated scope is a plain-text 400)no
422UNPARSEABLE_TEMPORALA time phrase the server cannot parse, in strict mode (natural_mode: "lenient" drops it instead)no
422EVAL_OVERRIDE_DISABLEDfacet_plan_override on /v1/answer without the evaluation flagno
503ANSWER_UNAVAILABLE/v1/answer or /v1/compose with no answer lane configuredno
502ANSWER_PROVIDER_ERRORThe answer model's provider refused the call (e.g. a model that rejects max_tokens)depends on the cause

Details: Recall, Answer, LLM & Answer.

Forget and erasure

StatusCodeWhenRetriable
422EMPTY_SELECTOR_WITHOUT_CONFIRMATIONAn empty selector without confirm_all: trueno
400AMBIGUOUS_SELECTOR_CONFIRM_ALLA selector together with confirm_all: true on /v1/forgetno
422UNKNOWN_PREVIEW_IDA from_preview_id that is unknown, expired, from before a restart, or for a different operationno
502FORGET_BACKEND_FAILED / ERASURE_BACKEND_FAILEDA store could not complete the deletion; nothing is reported as deletedyes
409SCOPE_STATE_CHANGEDA /v1/scopes change inside a running forget's or erasure's footprint; nothing was appliedyes, although the body says retriable: false (v0.10.2): re-send the mutation once the forget or erasure is done
409REDERIVE_IN_PROGRESSA forget, erasure or preview on a scope a re-derivation job holdsyes (Retry-After: 30)
409AUTHORIZATION_STATE_CHANGEDScopes were registered or removed inside a forget's, erasure's or erasure poll's footprint on each of 5 attempts to authorize it; nothing changedyes (Retry-After: 1)
503SERVER_SHUTTING_DOWNA forget or erasure sent after a graceful stop began; nothing changedyes (Retry-After: 5)

Details: Forget, Erasures.

Scopes, retention and usage

StatusCodeWhenRetriable
409SCOPE_REGISTRATION_EXISTSRegistering a scope that is already registeredno
422INVALID_RETENTION_POLICYA retention policy with a per-source key that is not source:<system>no
400INVALID_PERIOD / INVALID_ROLEAn unknown period or role on /v1/admin/usageno

Details: Scopes, Retention & WAL, Usage ledger.

Authentication and policy

StatusCodeWhenRetriable
401MISSING_TOKENNo bearer token on a server that requires one (an X-Cortex-Actor header alone is not enough)no
401INVALID_TOKEN_SIGNATURE / TOKEN_EXPIREDA token that does not verify, or has expiredno
401ACTOR_MISMATCHAn X-Cortex-Actor header that does not match the token's subjectno
403POLICY_DENIEDThe policy stack refuses the capabilityno
503NOT_CONFIGUREDToken minting (/v1/auth/signup, /v1/auth/tokens) on a keyed server without CORTEX_V1_MINTER_ENABLE=1no
429RATE_LIMITEDToo many requestsyes

Details: Authorization, Auth.

Admin and derived-data repair

StatusCodeWhenRetriable
422NO_TARGETSA re-derivation or unmerge request that names nothing to repairno
409ENRICHMENT_OFFPOST /v1/admin/derived/rederive with enrichment offno
404JOB_NOT_FOUNDAn unknown or another caller's re-derivation jobno
409JOB_MISMATCH, JOB_NOT_COMPLETED, JOB_ALREADY_CONTINUEDReusing or continuing a re-derivation job wronglyno
422COLD_BACKUP_ACK_REQUIRED, NO_ELIGIBLE_EVENTS, INVALID_AUDITA re-derivation apply without the backup acknowledgement, with nothing eligible, or with an unreadable audit reportno
409UNIFIED_WAL_REQUIREDsource-blob-links on the legacy dual WALno
503REDERIVE_UNSUPPORTEDThe coordinator cannot run re-derivationno
500REDERIVE_FAILED, REDERIVE_PLAN_FAILED, UNMERGE_FAILED, SOURCE_BLOB_LINKS_FAILED, ORPHAN_BLOB_REPORT_FAILED, CHUNK_INSPECTION_FAILEDThe operator route failed; the message says whyafter the cause is fixed

Details: Admin.

Code plane

StatusCodeWhenRetriable
503CODE_PLANE_DISABLEDAny /v1/code/* route with CORTEX_CODE_PLANE offno
404REPO_NOT_FOUNDAn unknown repository, or one you cannot seeno
422REPO_PATH_NOT_ALLOWEDA path outside CORTEX_CODE_REPO_ROOTS or always refused (details.reason)no
422REGISTRATION_FAILEDA repository path the server cannot register (e.g. a relative path)no
403SCOPE_REGISTRATION_REQUIREDRegistering a repository directly under a root scopeno
409REPO_SCOPE_IN_USEA scope binding another repository already holdsno
400INVALID_PATHSA malformed certify paths filterno

Details: Code Plane.

Blobs

StatusCodeWhenRetriable
415unsupported_media_typeA multipart/form-data upload (send the raw bytes instead)no
413(none)A body over 32 MiBno
422INVALID_IDEMPOTENCY_KEYAn idempotent blob route without X-Cortex-Idempotency-Keyno
409IDEMPOTENCY_CONFLICTThe same blob key with different bytesno

Details: Blobs.

Codes that changed in v0.10.2

  • A ?wait= capture that runs out answers 408 WAIT_TIMEOUT after about 30 s, not about 60 s, with details.waited_ms and details.waiting_on. A waiting bulk's budget now covers its inline indexing, so it can answer 408 (with details.event_ids) where it used to wait and answer 200.
  • A forget, erasure or erasure poll that raced a scope registration outside its footprint used to get a spurious 403 POLICY_DENIED (or 404 on GET /v1/erasures/{id}); it now proceeds. A registration inside the footprint on every attempt gives the retriable 409 AUTHORIZATION_STATE_CHANGED.
  • GET /v1/events/{id}?scope= adds 422 INVALID_SCOPE_GRAMMAR for a bad value.

Codes that changed in v0.10.1

  • A capture that waited on a running forget used to get 403 POLICY_DENIED; it now gets the retriable 409 DESTRUCTIVE_OPERATION_IN_PROGRESS.
  • Forgetting an id stored in another scope used to give 502 FORGET_BACKEND_FAILED; it now answers 200 with every count 0, like a missing id.
  • A ?wait=indexed capture that a concurrent forget blanked is no longer reported as 502 INDEXING_FAILED.
  • Cancelling a finished erasure job answers 404 NOT_FOUND (v0.9.13 answered 405).

Server start-up refusals (for example CLUSTER_MODE_UNSUPPORTED, exit code 78) are not HTTP errors; see Storage & Cluster and Configuration.

On this page