Errors

Status: Every code extracted from v2/api/worker.ts, v2/api/investigations.ts and v2/shared/errors.ts on 2026-10-30. Statuses verified at the fail() call sites.

The envelope

{ "error": { "code": "forbidden", "message": "Event access denied.", "trace_id": "…", "retryable": false } }

Codes are lowercase ^[a-z][a-z0-9_]{0,63}$ (unknown codes collapse to internal), messages truncate at 300 characters, and stack traces never cross the boundary. Responses are Cache-Control: private, no-store. Include trace_id in support reports.

400 — invalid request

CodeWhereMeaning
invalid_requestmost routesmalformed/oversized JSON body
invalid_event / invalid_event_updateeventsevent fields or update fields invalid
invalid_search / invalid_time_rangesearch, eventsterm too long, limit out of range, bad date bounds
invalid_entitlemententitlementsproduct/fields invalid
invalid_source / invalid_source_statesources, runsunsafe source target or bad PATCH body
invalid_storystoriestitle/notes/status invalid
invalid_actionOps actionsstatus or revision invalid
invalid_dashboarddashboardsconfig/title/visibility invalid
invalid_audit_queryadmin auditlimit outside 1–100
invalid_queryHQL, cubequery outside the bounded contract
invalid_investigation / invalid_investigation_iteminvestigationsfields, kinds or revision invalid
invalid_entity / invalid_relationshipentities, graphtype/name/evidence rules failed
invalid_graph_filtergraphbad investigation filter
invalid_statestory handoffstory not ready (409 at call site — see below)
query_failedHQL, cubeauthorized query failed at execution
invalid_callback / invalid_publication / invalid_evidence / invalid_manifestinternal routesAutomation callback/publication contract violations

401 — not authenticated

CodeMeaning
unauthorizedmissing/invalid API key or session; invalid callback signature (internal)

403 — not permitted

CodeMeaning
forbiddencapability missing, product not enabled, non-member key, missing organization header, or invalid assignment rule

A 403 is policy, not transient — do not retry unchanged.

404 — not in scope

CodeMeaning
not_foundrecord absent or outside the actor’s scope (deliberately indistinguishable)
run_not_foundrun state lost after registration

409 — conflict

CodeMeaningClient action
revision_conflictstale expected_revisionre-read, decide, retry
story_handed_offstory is immutable after handoffstop editing
invalid_statehandoff precondition (story not ready)fix state first
invalid_transitionOps action status machine rejects the moveconsult the transition table
idempotency_conflictidempotency key reused with a different sourceuse a fresh key
insufficient_evidencehandoff/brief without evidenceattach evidence first
artifact_missing / artifact_conflictinternal publication artifact checks failed—
invalid_run_stateinternal publication against non-active run—

413 / 429 / 5xx

StatusCodeMeaning
413too_largebody or callback payload over 65,536 bytes
429run_quota_exceededhourly workspace run quota reached — retry next window
500run_registration_failed / handoff_failedstate write failed; report with trace_id
503unavailablestorage or analytics dependency not provisioned
503automation_unavailableAutomation endpoint/token not configured

Retry rules

Retryable with backoff: 429 run_quota_exceeded (next window), 503 (later), 500 after status check, and 409 revision_conflict after re-reading. Never retry unchanged: 400, 401, 403, 404, 413.

See also