Error Response Format
Error messages returned to clients are sanitized. Raw provider details are never exposed. This prevents accidental leakage of prompt content through error responses.
Error Types
Retries
Consus Gateway automatically retries transient upstream errors once before returning an error to you. The retry delay depends on the error type:
For client-side retries, the OpenAI SDK has built-in retry logic that works out of the box. If you’re using raw HTTP, retry on
429 and 502 with exponential backoff: start at 1 second, double each attempt, and cap at 5 retries.
504 timeouts are not automatically retried — a request that exceeded its ceiling will usually exceed it again. When a non-streaming request hits the gateway’s limit, the 504 also carries the response header x-should-retry: false. The official Anthropic and OpenAI SDKs (and Claude Code) read that header before their own retry rule, so they surface the error once instead of re-sending the same request into the same limit. Before retrying yourself, either stream the request (stream: true raises the ceiling to ~15 minutes) or reduce the work in it (see Request Timeout).
Common Errors
Invalid model:destination_url, webhook_url, callback_url, forward_to, send_to, post_to, upload_url, ingest_url), the request is rejected at validation. The message identifies the tool and the offending parameter. See Chat Completions: Rejected Tool Schemas for the full list and rationale.
504 timeouts (for example a connection that never opened) keep the generic message and no x-should-retry header:
When
code is "upstream_rate_limit", the 429 came from the upstream model provider, not from your API key’s rate limit. API key rate limits are enforced at the API Gateway layer and return a 429 without a JSON body.When
code is "context_window_exceeded", the request can never succeed as sent — do not retry it. Trim or compact the conversation (agent harnesses: see Agent Harnesses & Context Windows) and resend. When the provider reports them, the message carries the attempted and maximum token counts.When
code is "unsupported_input_modality", the request was rejected before it reached any provider and can never succeed as sent — do not retry it. The message names the model, the part that was rejected (image_url or file), and the modality it needs. GET /v1/models → input_modalities is the authoritative list of what each model accepts; check it before attaching images or PDFs.content_policy_violation means the model provider’s safety system rejected the request before generating anything (Azure content filter, Bedrock usage policy, or a Gemini prompt block). It’s a 400 and is not retried; rephrase the request or use a different model.Responses stopped by provider safety
If a provider’s safety system stops a response mid-generation, the request still returns200, with finish_reason: "content_filter" on /v1/chat/completions (stop_reason: "refusal" on /v1/messages).
Changed October 2026 (
/v1/chat/completions): Claude refusals now return finish_reason: "content_filter" (was "stop"), and Bedrock stop-sequence matches return "stop" (was "length").Errors on streaming requests
A request that fails before the provider produces its first event — validation rejections, context-window overflows, provider faults during setup — returns its real HTTP status and the JSON error body above, even whenstream: true was requested. Branch on the status code exactly as you would for a non-streaming call; a 400 is terminal, a 502/503 is retryable.
Once streaming has begun (HTTP 200 committed and events flowing), a mid-stream failure is delivered in-band: an error frame on the SSE stream, followed by a clean close (data: [DONE] on /v1/chat/completions; an error event on /v1/messages and /v1/responses). Mid-stream errors after partial output are not automatically retryable — inspect the frame’s type and code before resending.