Skip to main content
Cogito returns a single, deterministic error shape on every failure:
Always log request_id. We trace it through the gateway, scheduler, and inference cluster. Support can pinpoint your request from this single ID. error.param is a string or null: when set it points at the offending request field. Codes that populate it today: context_length_exceeded sets it to "messages", "prompt", or "max_tokens"; invalid_image_format sets it to the path of the rejected image part (e.g. "messages[1].content[2].image_url.url"); grammar_not_supported sets it to "response_format" or "tool_choice"; invalid_tool_call_arguments sets it to the path of the offending arguments string (e.g. "messages[1].tool_calls[0].function.arguments"); and backend_invalid_argument relays the serving stack’s own param path when it provides one. On every other error it is null.

Error types

error.type is set per HTTP status by the gateway. The mapping is deterministic — the table below is the full set you can encounter.

Common codes

error.code is the machine-readable handle. Always log it alongside request_id. Grouped by category: Auth
  • invalid_api_key — Bearer header missing or revoked (401)
  • missing_authorization — no Bearer header at all (401)
Billing
  • insufficient_quota — balance ≤ 0 (402). The wire code matches error.type — both are insufficient_quota. Renamed from the earlier insufficient_balance for OpenAI parity.
  • spend_cap_reached — month-to-date spend has hit your hard cap (429). Renamed from the earlier spend_capped. Raise the cap in the dashboard or wait for the month to roll over.
  • billing_not_configured — server misconfiguration on our side (503)
Validation
  • invalid_request_error — generic body-shape failure (400)
  • model_not_found — slug typo or model retired (404)
  • context_length_exceeded — the serving route rejected input that cannot fit the model’s context window (400). Ultra-fast routes can reject estimated input or input plus an explicit max_tokens budget before dispatch; other routes validate with their serving tokenizer and may clamp only the output budget. Compact or shorten the input before retrying; error.param names the offending field when available: messages, prompt, or max_tokens.
  • invalid_image_format — an image_url part carries data that is not a decodable image (400): wrong bytes for any supported format, empty or invalid base64, or a format the serving stack cannot decode (e.g. HEIC). Send png, jpeg, gif, or webp; error.param is the path of the rejected part (e.g. messages[0].content[1].image_url.url). Do not retry unchanged — the same payload will always be rejected.
  • grammar_not_supported — the request pinned grammar-constrained output (response_format with json_schema, or a forced tool_choice) on a serving route that runs no grammar backend (400). error.param is response_format or tool_choice. Do not retry unchanged.
  • invalid_tool_call_arguments — a replayed assistant tool_calls[] entry (or a Responses function_call input item) carries function.arguments that is not a string containing a JSON object (400). The serving stack cannot render the chat template for such a conversation. error.param is the path of the offending string (e.g. messages[1].tool_calls[0].function.arguments). Fix the replayed arguments before retrying — the same history will always be rejected.
  • backend_invalid_argument — the serving stack rejected the request as invalid with its own explicit 4xx verdict (400): an image URL that could not be fetched, a schema its grammar compiler cannot express, and similar request-content faults. error.message carries the serving stack’s detail and error.param the offending field path when available. Do not retry unchanged — the same request will be rejected again.
Upstream / cluster
  • backend_unavailable — gateway-side error before reaching the upstream (e.g. missing backend credentials) (500, surfaces as error.type: api_error)
  • upstream_unavailable — TCP/connection failure to the upstream cluster (502, surfaces as error.type: api_error)
  • upstream_<status> — verbatim upstream HTTP status pass-through (e.g. upstream_503 when the inference cluster itself returned 503)

Retry-after

429 and 503 responses include a Retry-After header (seconds). Honor it. Exponential backoff on top of Retry-After is fine; ignoring it will get you rate-limited harder.