Skip to main content
Every SDK raises the same Bedrock-named exceptions, so your existing error-handling paths — including catch-and-backoff logic keyed on ThrottlingException — port over unchanged. Every server-derived error carries message, statusCode, errorCode, requestId (quote it to support), retryAfterSeconds, and the raw response body.

Retry policy (Bedrock standard-mode analog)

  • Attempts = maxRetries + 1; the default is 2 retries (3 total attempts).
  • Retried: network errors, HTTP 429, 500, 502, 503, 504, and 408 — with full-jitter exponential backoff capped at 20 s, honoring any Retry-After header.
  • Never retried: auth failures, validation errors, unknown models, and budget exhaustion (BUDGET_EXCEEDED) — spending errors must never silently retry.
  • Streaming: retries apply only until response headers arrive. Once the first byte of the stream is consumed, a drop surfaces as ModelStreamErrorException — a partial generation is never silently replayed.

What every error tells you

Every error the gateway answers, in any dialect, says three things:
  • What happened — message, in plain language. When a model provider is involved, the message names the provider; when the fault is ours, it says so and confirms you were not charged.
  • Who has to act — source:
    • client: change the request, key, model, or budget. Retrying the same request will fail the same way.
    • provider: the upstream model provider failed or throttled the request. Retry shortly or switch models.
    • platform: an AI Reserve component failed. A request that never reached the model is not billed; the message says so when that is the case. Retry shortly; if it persists, contact support with the request id.
  • How to find it — request_id in the body and the X-Request-ID response header. /v1/messages answers it as request-id (the header the Anthropic SDKs surface as request_id); the Bedrock-compatible routes as x-amzn-RequestId. Quote it to support.
hint, when present, is a one-line next step (for example, set "stream": true for long generations that hit the gateway’s first-byte budget).

Wire shapes

Status codes and error codes

Every status/code pair the gateway answers. Every 429 rate limit and every 503 AI Reserve answers itself carries Retry-After on every dialect; spend caps never do (they do not lift on their own), and provider 429/503s are relayed with the provider’s status.

Errors inside a stream

Once a stream has started the HTTP status is already 200, so a failure arrives as a terminal frame instead:
  • OpenAI-compatible routes write one last data: line with the error envelope — {"error":{"message","type":"api_error","code":"stream_error","source","hint"}} — and end the stream. No [DONE] follows.
  • /v1/messages writes an Anthropic event: error block — {"type":"error","error":{"type","message","source","hint"}}.
  • /model/{modelId}/converse-stream writes an exception event (internalServerException, modelStreamErrorException, …) in the Bedrock event-stream encoding.
A partial generation is never billed as a complete one, and the SDKs raise ModelStreamErrorException rather than replaying it.