Skip to content

Errors & status codes

The gateway uses standard HTTP status codes alongside a JSON error body with a machine-readable code field. Always branch on code, not on the human-readable message (which may change).

{
"error": {
"code": "policy_block",
"message": "Request blocked by policy rule."
}
}
Code HTTP Retry? Meaning
invalid_api_key 401 No API key not found, revoked, or malformed. Check the key and the Authorization / X-API-Key header.
policy_block 403 No The Policy Engine’s terminal action was BLOCK. The X-Matched-Rule response header names the rule.
model_not_found 404 No The requested provider/model-id is not recognized or not available to your org.
context_length_exceeded 400 No The request exceeds the model’s context window. Shorten the input.
invalid_request 400 No Malformed request body (bad JSON, missing required field, wrong type).
quota_exceeded 429 Backoff Rate limit or token budget exceeded. See Rate limits.
provider_unavailable 503 Backoff Every provider in the routing chain was unavailable.

On a policy_block, the error body carries two extra fields beyond code and message: type ("policy_error") and rule_id (the rule that produced the block, matching the X-Matched-Rule header). The rule_id also matches matched_rule_id in the audit log, so you can cross-reference an unexpected block. See Policy decisions for the full body.

  • Do not retry 4xx errors except 429 — they are deterministic and will fail identically. Fix the request instead.
  • Retry with exponential backoff on 429 (quota_exceeded) and 503 (provider_unavailable). Start at ~1s, double each attempt, cap at ~30s, and add jitter. Honor X-RateLimit-Reset on 429 (see Rate limits).
  • policy_block is intentional. A 403 policy_block means your organization’s policy blocked the content — surface it to the user; do not retry.

DLP redaction is not an error. When DLP redacts content inline, the request still succeeds (200) with the content modified. In streaming responses you may also receive dlp_correction events (content was corrected mid-stream) and output_blocked events (the response was stopped by DLP). See DLP results.

BLOCK is the only terminal policy action that returns a non-2xx status (403 policy_block). The other actions surface on a successful response — read the X-Policy-Action header to tell them apart:

  • REDACT and ROUTE_TO return 200; the content was sanitized or the request was rerouted, and your call succeeded normally.
  • CANCEL returns 200 with a truncated stream — the output was halted mid-response. Treat the partial content as incomplete; the request cannot be retried because the provider round-trip already happened.

See Policy decisions for the full semantics of each action.

  • Rate limits — headers and backoff for 429 quota_exceeded.
  • Policy decisions — how BLOCK, REDACT, ROUTE_TO, and CANCEL are decided and surfaced.
  • Chat completions — streaming dlp_correction and output_blocked events.