Client API Errors
OMNI Client API guarantees machine-readable failures across REST (/v1/*) and hosted MCP (/mcp).
This page is the authoritative v1.5 error contract.
Contract guarantees
error.typeanderror.codeare stable for programmatic branching.error.messageis human-readable and can change; never parse it.error.request_id(REST) anderror.data.request_id(MCP JSON-RPC) are required support correlation keys.- New error codes can be added during beta; existing codes are not silently repurposed.
REST error envelope
Diagnostic headers to log on every failure
X-Request-IdOmni-Required-Scopes(on403 insufficient_scope)Retry-After(on429 rate_limit_exceeded)Idempotency-Replayed: true(idempotent replay responses)
HTTP class mapping
error.type | Typical HTTP |
|---|---|
invalid_request | 400, 409 |
auth_error | 401, 403 |
permission_error | 403 |
rate_limit_error | 429 |
api_error | 500, 502, 503, 504 |
Exhaustive v1.5 REST code registry
Derived from live handlers inwebapp/client_api.py.
error.type | error.code | HTTP | Retry? | Trigger |
|---|---|---|---|---|
auth_error | missing_api_key | 401 | No | Missing/malformed bearer token |
auth_error | invalid_api_key | 401 | No | Invalid format, revoked key, or unauthorized key resolution |
auth_error | auth_rejected | 403 | No | Key rejected by control plane |
permission_error | insufficient_scope | 403 | No | Required scope missing |
rate_limit_error | rate_limit_exceeded | 429 | Yes | Burst or sustained per-key limit exceeded |
invalid_request | invalid_parameter | 400 | No | Invalid integer/parameter coercion |
invalid_request | missing_q | 400 | No | fred.search missing q |
invalid_request | missing_series_id | 400 | No | fred.series missing series_id |
invalid_request | unknown_tool | 400 | No | Unknown tool ID |
invalid_request | missing_idempotency_key | 400 | No | Missing header for mutating invoke/call |
invalid_request | invalid_json | 400 | No | Body not valid JSON |
invalid_request | invalid_payload | 400 | No | Request schema invalid |
invalid_request | idempotency_conflict | 409 | Yes | Same idempotency key currently in-flight |
api_error | service_disabled | 503 | Yes | Kill switch enabled |
api_error | auth_backend_unavailable | 503 | Yes | Control plane unavailable |
api_error | invalid_control_plane_response | 503 | Yes | Control plane payload invalid/incomplete |
invalid_request | fred_invalid_request | 4xx passthrough | No | Upstream FRED rejected request |
api_error | fred_upstream_error | 5xx passthrough | Yes | Upstream FRED transient/server failure |
invalid_request or api_error | mcp_invocation_failed | passthrough | 5xx only | MCP invoke path failed; type depends on surfaced status |
Endpoint-to-code coverage matrix (REST)
| Endpoint | Declared code set |
|---|---|
GET /v1/health | missing_api_key, invalid_api_key, auth_rejected, rate_limit_exceeded, service_disabled, auth_backend_unavailable, invalid_control_plane_response, insufficient_scope |
GET /v1/openapi.json | missing_api_key, invalid_api_key, auth_rejected, rate_limit_exceeded, service_disabled, auth_backend_unavailable, invalid_control_plane_response, insufficient_scope |
GET /v1/fred/search | missing_q, invalid_parameter, fred_invalid_request, fred_upstream_error, plus auth/scope/rate/system codes |
GET /v1/fred/series/{series_id} | missing_series_id, invalid_parameter, fred_invalid_request, fred_upstream_error, plus auth/scope/rate/system codes |
GET /v1/mcp/tools | auth/scope/rate/system codes |
POST /v1/mcp/invoke | missing_idempotency_key, invalid_json, invalid_payload, unknown_tool, idempotency_conflict, mcp_invocation_failed, plus auth/scope/rate/system codes |
GET /mcp | auth/scope/rate/system codes |
DELETE /mcp | auth/scope/rate/system codes |
GET /sse | auth/scope/rate/system codes |
Hosted MCP JSON-RPC error envelope
JSON-RPC code mapping
| JSON-RPC code | Category | Typical source |
|---|---|---|
-32700 | Parse error | Invalid JSON body before routing |
-32600 | Invalid request | Missing/invalid JSON-RPC envelope or method |
-32601 | Method not found | Unsupported MCP method |
-32602 | Invalid params | Missing tool name, missing idempotency key, invalid params |
-32001 | Auth/permission | Mapped auth_error and permission_error |
-32002 | Rate limiting | Mapped rate_limit_error |
-32603 | Internal error | Mapped api_error and unhandled internal failures |
omni_code to JSON-RPC mapping
omni_code | JSON-RPC code | Retry? |
|---|---|---|
missing_api_key, invalid_api_key, auth_rejected, insufficient_scope | -32001 | No |
rate_limit_exceeded | -32002 | Yes |
missing_idempotency_key, invalid_payload, unknown_tool, idempotency_conflict, fred_invalid_request | -32602 | idempotency_conflict only |
auth_backend_unavailable, invalid_control_plane_response, service_disabled, fred_upstream_error, mcp_internal_error | -32603 | Yes |
- Transport-level parse/request failures (
-32700,-32600,-32601) can omitomni_code. request_idis always present in hosted MCP error payloads.
Retry policy (authoritative)
| Condition | Retry? | Rule |
|---|---|---|
429 rate_limit_exceeded / -32002 | Yes | Honor Retry-After; otherwise bounded exponential backoff + jitter |
503 auth_backend_unavailable / 503 invalid_control_plane_response | Yes | Bounded backoff + jitter |
409 idempotency_conflict | Yes | Retry with same idempotency key |
fred_upstream_error (5xx) | Yes | Retry idempotently with bounded backoff |
400 invalid_request* / -32602 | No | Fix request first |
401/403 auth/scope | No | Fix key/scopes first |
Deterministic handling algorithm
- Parse only machine fields (
error.type,error.code, JSON-RPCerror.code,omni_code). - Retry only transient classes (
429,5xx, retryable JSON-RPC classes). - Reuse idempotency key on all retried write-like operations.
- Emit structured logs with endpoint/method, idempotency key, and request id.
- Escalate persistent failures with request IDs and retry history.
Related docs
/sources/client-api-reference/sources/client-api-endpoints/sources/client-api-retries/sources/client-api-mcp-hosted