Switchboard

Docs

Errors

Codes, retry rules, MCP failures.

Failures on JSON ops/proxy return an envelope with data: null and an error object. HTTP status matches the failure class.

Envelope error body

{
  "data": null,
  "meta": {
    "schema": "v1",
    "request_id": "req_…",
    "outcome": "failed",
    "cache": "bypass",
    "latency_ms": { "hub": 0.3 }
  },
  "error": {
    "code": "rate_limited",
    "message": "rate limit exceeded (61/60 in 60s)",
    "retryable": true,
    "request_id": "req_…",
    "retry_after_ms": 1000
  }
}

When retry_after_ms is present the response also includes an HTTP Retry-After header (seconds, rounded up). Prefer retry_after_ms in SDKs; use the header for generic HTTP clients.

Catalog

Code HTTP Retry? Meaning What to do
unauthorized 401 no Missing/invalid Bearer key Check Authorization; republish LKG after mint/rotate
forbidden_scope 403 no Key lacks connector/op/category scope Widen scopes; republish LKG
forbidden_role 403 no Key role cannot access this route Use an app/admin key with the right role
forbidden_ip 403 no Caller IP not on allowlist Update key IP policy
forbidden_plan 403 no Plan cannot use this thinking tier Upgrade plan or pick a lower tier (anybody / thinker / expert)
forbidden_model 403 no Model not allowed for this key Request model allowlist change or pick an allowed model
invalid_input 400 no Bad path/body/unknown op Fix request; include Idempotency-Key when required
invalid_request 400 no Malformed form / request parse Fix encoding / content-type
body_too_large 413 no Request body over limit Shrink payload
pii_blocked 400 no Payload failed PII policy Redact fields or change data policy
region_unavailable 403 no No egress for requested region Pick a supported SB-Region / cell
rate_limited 429 yes RPM/TPM, lane contention, or anomaly throttle Wait retry_after_ms (default 1000); reuse Idempotency-Key
budget_exceeded 402 no\* Soft/hard spend cap blocked admit Raise tenant budget or wait; backoff uses retry_after_ms (default 60000) so clients do not hammer
insufficient_credits 402 no\* Prepaid balance empty Top up credits; same backoff hint as budget
dedupe_unavailable 503 yes Hub idempotency store down Retry with the same Idempotency-Key after retry_after_ms
provider_down 502/503 yes Upstream/provider failure or empty ladder Fail over cells; retry with same idempotency key
approval_denied 403 no Operator denied the side-effect tool call Do not retry; change the action or get approval
approval_pending 200 (MCP) poll Side-effect tool awaiting approve/deny Poll approval status; do not re-issue a new idempotency key
unavailable 503 no Feature not loaded (e.g. thinking tiers) Operator must load config; retry later
internal 500 sometimes Unexpected hub error Retry only if retryable: true

\*Not auto-retryable for spend — raising budget/credits is required — but retry_after_ms + Retry-After are still set so clients back off cleanly.

Retry rules for agents and SDKs

  • Honor error.retry_after_ms / Retry-After on 429, budget, lane, and retryable 5xx.
  • Retry connection errors and 503 across the cell endpoint list; reuse the same Idempotency-Key.
  • Do not retry non-idempotent 4xx (forbidden_scope, invalid_input, unauthorized, pii_blocked, forbidden_plan, forbidden_model).
  • @switchboard/sdk SwitchboardClient already fails over ordered endpoints on connection/503.

MCP errors

MCP uses JSON-RPC error objects (code integer + message), not the HTTP envelope, on the MCP response body. HTTP auth failures may still return the envelope. Approval flows surface approval_pending / approval_denied in the MCP result / error string.