Retry and fallback logic is where multi-platform Claude deployments earn their keep: when one surface throttles or overloads, traffic shifts to another. But that only works if your code can recognize "throttled" and "overloaded" no matter which platform said it. The trick is to stop branching on platform-specific exception types and normalize every failure to the same two facts Anthropic's own API reports: the HTTP status code and the error type string.
The canonical vocabulary
Anthropic's error model is a JSON body with "type": "error", an error object carrying type and message, and a request ID. The status-to-type mapping is stable:
| Status | Error type | Retryable? |
|---|---|---|
| 400 | invalid_request_error | No — fix the request |
| 401 / 402 / 403 / 404 | authentication_error / billing_error / permission_error / not_found_error | No — fix credentials, billing, or routing |
| 413 | request_too_large | No — shrink the payload |
| 429 | rate_limit_error | Yes — honor retry-after |
| 500 / 504 | api_error / timeout_error | Yes — backoff |
| 529 | overloaded_error | Yes — backoff, or fail over |
The retry rule is equally compact: 429, 5xx, and connection errors are retryable with exponential backoff; the 4xx family is not — retrying a 400 just resends a broken request.
What each platform wraps around this
Bedrock. On the legacy InvokeModel/Converse surface, calls go through AWS SDKs, so failures arrive as AWS SDK exceptions — for example, a missing Marketplace prerequisite surfaces as AccessDeniedException — and your code has to map AWS exception names back to retryability. The current "Claude in Amazon Bedrock" surface speaks the Anthropic Messages API at the bedrock-mantle endpoint, and its admission control returns a straightforward 429 when a request would exceed the token-per-minute quota.
Vertex AI. Requests go to Google's rawPredict/streamRawPredict endpoints, so raw HTTP integrations see Google API error structures around the failure, and Google Cloud quota semantics (QPM/TPM buckets) drive when 429s appear.
Foundry. Claude sits behind Azure API management, and responses carry an apim-request-id header alongside Anthropic's request-id — keep both for support tickets, since they trace the Azure and Anthropic halves of the path. Foundry also does not return Anthropic's anthropic-ratelimit-* headers, so you cannot read remaining quota; Anthropic's guidance is Azure monitoring plus exponential backoff on 429s.
Claude Platform on AWS. This surface returns the Claude API's native errors, with two request IDs per response: x-amzn-requestid for AWS support and request-id for Anthropic support. One local idiom worth knowing: a 403 means the request reached the server — check the workspace ID and IAM actions rather than your network path.
The normalization shortcut: one SDK, typed exceptions
If you use Anthropic's Python SDK provider clients — AnthropicBedrockMantle(aws_region=...), AnthropicVertex(project_id=..., region=...), AnthropicFoundry(api_key=..., resource=...), AnthropicAWS() — most of the normalization is done for you. All of them raise the same typed exception hierarchy (RateLimitError, InternalServerError, APIConnectionError, and so on), auto-retry retryable failures twice by default while honoring retry-after, and expose the canonical error type string via the .type property on every APIStatusError. Your fallback logic can then be written once:
from anthropic import APIConnectionError, APIStatusError, AnthropicVertex
client = AnthropicVertex(project_id="my-project", region="global")
RETRYABLE = {"rate_limit_error", "overloaded_error",
"api_error", "timeout_error"}
try:
msg = client.messages.create(
model="claude-sonnet-5", max_tokens=1024,
messages=[{"role": "user", "content": "Hello"}])
except APIConnectionError:
route_to_fallback_platform() # network-level: retryable
except APIStatusError as e:
if e.type in RETRYABLE:
route_to_fallback_platform() # same check on every platform
else:
raise # 4xx: fix the request, don't retry
Swap the client class and model-ID form and the except blocks stay identical on all four platforms. If you keep raw HTTP or cloud-native SDK paths (boto3 on legacy Bedrock, Google clients on Vertex), write a thin adapter that extracts the HTTP status and, where present, the Anthropic error type from the body, and emits the same normalized tuple.
Two portability caveats
Mid-stream errors don't have a status code. With streaming, an error can occur after the 200 response has started and arrives as an SSE error event, not an HTTP status — your normalizer needs a path for that (see mid-stream error events). 529 is your failover signal. overloaded_error reflects platform-wide load, and Claude Platform on AWS runs a capacity pool separate from both the first-party API and Bedrock — which is precisely what makes cross-platform fallback on 529 worth building.
Where to go next
Start with the API error codes reference and SDK error handling, then the per-platform guides: Bedrock, Vertex, Foundry, and Claude Platform on AWS.