Handle Cloud Errors

Su Suriya Ravichandran Updated 10 Nov 2026
6 min read ·Lesson 168 of 200

The Same Classes, Different Causes

Lesson 141 introduced the SDK's error classes, and they apply to every integration: a 401 is an AuthenticationError whether the request went to the direct API or to a cloud platform. What differs is the cause. On the direct API, an authentication failure usually means a wrong or revoked key. On a cloud platform, the same status can mean that the identity lacks a permission, that the model has not been enabled in the account, or that the request was sent to a region where the model is not offered.

Cloud integrations also add failures that never reach the Claude service at all. A missing credential, an unreadable identity file, or a configuration that names a project that does not exist can all stop a request before it is sent. Those errors come from the cloud's own libraries, and they may not look like API errors at all. This lesson shows how to tell the two apart, how to map each cause to the action that resolves it, and how to log the information that makes the diagnosis quick.


Two Places a Failure Can Start

Before reading an error's class, decide where the failure began. A request that never leaves the process fails in the cloud's credential or configuration layer, and a request that reaches the platform fails in the platform itself:

Where it failsTypical symptomWhat to check
Before sendingAn error about missing credentials, a configuration value, or an unreadable fileThe credential chain, environment variables, and configuration (Lessons 164 and 167)
At the platformAn SDK error with a status code and a bodyThe platform's permissions, model access, region, and quotas
In the networkA connection or timeout errorThe network path to the platform's endpoint (Lesson 145)

The first row matters most for cloud deployments, because it looks different from everything else. If an application that worked yesterday now reports a credential error before any request, the cause is almost always a change in the environment, not in the API.


Mapping Status Codes to Causes

For failures that do reach the platform, the status code and the message narrow the cause. The mapping below is a working guide. The message text is the most precise evidence, and the platform's error reference is the authority for the exact wording:

StatusClassCommon cloud causeAction
400BadRequestErrorA model identifier from another platform, or a parameter the platform does not acceptCorrect the identifier or the parameter for this platform
401AuthenticationErrorMissing or expired credentialsRefresh or reconfigure the credential
403PermissionDeniedErrorThe identity lacks permission for the action, or the account has not enabled the modelGrant the permission, or enable the model in the account
404NotFoundErrorThe model is not offered in the chosen region, or the deployment or resource name is wrongChoose a region that offers the model, or correct the name
429RateLimitErrorThroughput or quota is exhausted for the account or the regionBack off (Lessons 142 and 146), and check the quota
5xxInternalServerErrorA problem on the platform sideRetry with backoff (Lesson 143)

Two rows are easy to confuse. A 403 says the identity may not do this, while a 404 can say the model is not there at all, and the remedy for each is different. Reading the message before acting prevents a week spent granting permissions for a model that is not offered in the region.


Classifying Cloud Failures

The diagnosis can be automated for the common cases, so the log says what to do rather than only what happened. The classifier below maps an error and its platform to a cause and an action. It uses simulated errors, so it runs offline:

"""cloud_errors.py: map an SDK error from a cloud platform to a likely cause and an action."""

from api_errors import fake_status_error
from anthropic import APIConnectionError, APIStatusError
import httpx

REQUEST = httpx.Request("POST", "https://example.invalid/v1/messages")


def diagnose(error: Exception, platform: str) -> str:
    if isinstance(error, APIConnectionError):
        return f"{platform}: no response; check the network path to the endpoint"
    if isinstance(error, APIStatusError):
        status = error.status_code
        if status == 400:
            return f"{platform}: bad request; check the model identifier and parameters for this platform"
        if status == 401:
            return f"{platform}: not authenticated; refresh or reconfigure the credential"
        if status == 403:
            return f"{platform}: not permitted; check the identity's permissions and the model's enablement"
        if status == 404:
            return f"{platform}: not found; check the region offers the model, and the name is correct"
        if status == 429:
            return f"{platform}: rate limited; back off and check the quota"
        if status >= 500:
            return f"{platform}: platform error; retry with backoff"
    return f"{platform}: unrecognized failure; read the error message and the platform's error reference"


if __name__ == "__main__":
    cases = [
        ("bedrock", fake_status_error(403, "permission_error", "not authorized", "req_1")),
        ("vertex", fake_status_error(404, "not_found_error", "model not found in region", "req_2")),
        ("foundry", fake_status_error(429, "rate_limit_error", "quota exceeded", "req_3")),
        ("bedrock", APIConnectionError(request=REQUEST)),
    ]
    for platform, error in cases:
        print(diagnose(error, platform))

Output:

bedrock: not permitted; check the identity's permissions and the model's enablement
vertex: not found; check the region offers the model, and the name is correct
foundry: rate limited; back off and check the quota
bedrock: no response; check the network path to the endpoint

How It Works

  1. Connection errors are checked first, because they carry no status and would otherwise fall through to the generic message.
  2. The status is mapped to a cause and an action, and each message names the thing to check. A 403 points at permissions and enablement, which is where a cloud denial usually lies.
  3. The platform name is part of every message, so a log line from a multi-platform application shows which integration failed.
  4. Unknown failures get a message that points to the reference, rather than a guess that could send someone in the wrong direction.
  5. The example errors are simulated with the helper from Lesson 141, so the classifier can be tested without access to any platform.

Before-Request Failures

Credential and configuration failures happen before a request is sent, so they will not appear in the API's request IDs, and they may come from a library other than the SDK. The application should catch them where it creates the client, at startup, and report them clearly. A failure at startup is far better than a failure on the first user request, and the factory in Lesson 167 is where such checks belong.


Logging Cloud Failures

Lesson 147's structured logs apply to cloud failures too, with two additions: the platform name, so the event is attributed correctly, and the classified cause, so an operator can act without reading the raw error. The request ID remains the key for support, when the failure reached the platform. For failures before a request, the log records the configuration step that failed, and never the credential value (Lesson 164).


Summary

Cloud integrations return the same error classes as the direct API, but the same status can have different causes on each platform. Some failures happen before any request, in the cloud's own credential and configuration layers. The status and message narrow the cause to permissions, enablement, region, identifiers, or quotas, and each cause has a different action. Classifying failures automatically, with the platform named in every log line, turns a confusing error into an instruction. The next lesson covers the extras that each cloud's SDK support adds on top of the shared client.

0 Comments

Reviewed before they appear

No comments yet.

Anthropic SDK Using Python
Anthropic SDK Intro Claude API Intro SDK Requirements Install Anthropic SDK Upgrade the SDK Create an API Key Set API Keys Use Environment Variables Import Anthropic Create a Client Send Your First Message Choose a Claude Model Set Max Tokens Read a Response Print Response Text Understand Message Blocks Use System Prompts Send User Messages Set Temperature Handle Stop Reasons Messages API Intro Create Messages Use Message Roles Send Conversation History Continue a Conversation Build a Chat Loop Reset Chat History Use Multiple Turns Inspect Message IDs Read Usage Data Write Clear Prompts Set a System Prompt Add Context to Prompts Use Prompt Templates Add Examples to Prompts Request JSON Output Use XML Tags Control Response Length Improve Prompt Quality Avoid Prompt Injection Read Text Blocks Read Content Blocks Check Stop Reasons Count Input Tokens Count Output Tokens Count Tokens Before Sending Limit Output Tokens Use Stop Sequences Read Request IDs Parse API Responses Streaming Intro Stream Text Output Use Stream Events Use Stream Helpers Get Final Messages Stream Async Responses Handle Stream Errors Build a Live Chat Stream Long Responses Close Streams Safely Build a Chatbot Keep Chat History Manage Chat Sessions Add Chat Memory Build a CLI Chatbot Build a Web Chatbot Use Flask with Claude Use FastAPI with Claude Return JSON from an API Add Chat Error Messages Async SDK Intro Create an Async Client Send Async Messages Use asyncio Run Parallel Requests Stream Async Text Handle Async Errors Set Async Timeouts Close Async Clients Choose Sync or Async Tool Use Intro Define a Tool Create Tool Schemas Send Tools to Claude Read Tool Calls Run Python Tools Return Tool Results Continue After Tool Use Control Tool Choice Handle Tool Errors Use the beta_tool Decorator Create a Tool Runner Add Tool Docstrings Validate Tool Inputs Use Multiple Tools Limit Tool Calls Log Tool Activity Build a Weather Tool Build a Search Tool Build a Calculator Tool Structured Output Intro Request JSON Data Validate JSON Output Use Pydantic Models Handle Invalid JSON Extract Fields from Text Generate Typed Data Use Image URLs Send Base64 Images Read PDFs with Claude Use Output Schemas Build Data Extraction Test Structured Responses Send Image Inputs Upload Files Use File IDs Process Text Files Summarize Documents Extract Table Data Handle File Errors Read Cache Usage Reduce Repeated Input Costs Debug Cache Misses Prompt Caching Intro Enable Prompt Caching Cache System Prompts Cache Long Context Test Cache Performance Use Cache Breakpoints Cache Best Practices Message Batches Intro Create a Message Batch Set Batch IDs Check Batch Status List Message Batches Get Batch Results Process Batch Outputs Handle Failed Batch Items Use Batches for Bulk Tasks Compare Batches and Requests Handle API Errors Handle Rate Limits Retry Failed Requests Set Request Timeouts Handle Network Errors Use Exponential Backoff Build Reliable API Calls Use Extended Thinking Log API Errors Track Request IDs Paginate API Results Set Thinking Budgets Read Thinking Blocks Use Tool Search Use Web Search Tools Use Computer Tools Use Citations Use Token Counting Read Raw Responses Set Custom Headers Use Claude on AWS Bedrock Use Claude on Vertex AI Use Claude on Microsoft Foundry Configure Cloud Credentials Choose a Cloud Provider Compare API Integrations Configure Provider Clients Handle Cloud Errors Use Cloud SDK Extras Deploy Cloud Apps Protect API Keys Use a .env File Ignore Secrets in Git Validate User Input Reduce Prompt Injection Limit Tool Permissions Avoid Unsafe Tool Calls Sanitize Tool Results Set Usage Limits Review Security Logs Test SDK Functions Mock API Responses Test Error Handling Test Streaming Code Measure Token Usage Track API Costs Configure Logging Deploy with Docker Deploy a FastAPI App Monitor Production Apps Build a Claude Chatbot Build a Text Summarizer Build a Code Explainer Build a JSON Extractor Build a PDF Assistant Build a Streaming Chat App Build a Tool-Calling Agent Build a Batch Processor Build a Research Assistant Build a Claude API Dashboard
Ask about this post
AI Ask about this post

Ask questions about Handle Cloud Errors and get answers drawn from it.

Signed-in readers only.