ClaudeAPI integrationLevel 3: Workflows

How Do You Get Claude to Handle API Errors Properly?

Have it build a table first: every failure the API documents, and what your code does about each one, whether that's retry, fail fast, tell the user or degrade. Only then have it write the happy path. The Claude API makes a good test case, because one status code can mean two different things.

Prompt to copy
I'm integrating [API] for [purpose]. Here's its error documentation: [paste it, or give the file path].

Don't write the client yet. Build a table with one row per failure the docs list, plus timeouts, dropped connections and a response that doesn't match the documented shape. Columns:
- how to recognize it: status code, error type, headers
- whether a retry can help, and how long to wait
- whether the request may have taken effect, so a retry could run it twice
- what the caller sees
- what gets logged, including the request ID

Where one status code has several meanings, give each its own row. Mark anything you assumed rather than read in the docs. Also list what [SDK name, if any] already retries, so the code doesn't retry on top of it.

When I approve the table, write the client from it, and add a test for each row using a mocked response.
A retry can help
  • Connection errors and timeouts
  • 408 and 5xx, including 529
  • 429 with a retry-after header
A retry won't help
  • 400: bad request or your own spend limit
  • 401, 403 and 404
  • 429 with no retry-after: the spend cap
Based on Anthropic's Claude API and SDK docs. Other APIs differ, so build your version from their error page.

Try it now

  1. 1Paste the prompt with the real error page for your API. For the Claude API, that's https://platform.claude.com/docs/en/api/errors.md.
  2. 2Read every row marked as assumed, and check it against the docs.
  3. 3Approve the table, then run the tests Claude writes for it.
  4. 4Force one real failure, such as a bad API key. It worked if you get a clear authentication error at the call site, not a crash three layers away.

Use it when

Any integration on a path that matters: payments, auth, messages to customers or paid model calls. The more a silent failure costs, the more this pays off.

Skip it when

A one-off script you'll watch and rerun. Also check what your SDK already does before you ask for more. Anthropic's Python SDK retries connection errors, 408, 409, 429 and 5xx responses twice by default, with backoff. A retry loop around it multiplies the attempts.

Why it works

A retry policy copied from a template treats every 429 alike. Anthropic's docs show why that fails. A rate-limit 429 usually has a retry-after header. A monthly spend-cap 429 has the same rate_limit_error type, no retry-after, and error.details.error_code set to enforced_spend_limit_reached, and it keeps failing until access resumes or you move up a tier. A spend limit you set yourself returns a 400. A 529 overloaded_error is temporary. A stream can also deliver an error after a 200 response, so a status check alone misses it. A table built from the real docs surfaces these differences, and a model working from memory may not know them.

Example

Say a Python service calls the Claude API. Your table might read like this. anthropic.RateLimitError with retry-after: let the SDK retry. enforced_spend_limit_reached: alert someone, and don't retry. anthropic.BadRequestError with a message starting You have reached your specified API usage limits: raise the limit. AuthenticationError or PermissionDeniedError: fail fast. APITimeoutError: the default timeout is 10 minutes, so set a shorter one for anything a user is waiting on. Log message._request_id on successful calls and request_id from error bodies, since Anthropic asks for that ID in support requests.

Going further

Separate definitely failed from unknown outcome. A timeout on a write means you can't tell whether it happened, and a plain retry could run it twice. Stripe's answer is an Idempotency-Key header on POST requests. In its API v1 docs, a retry with the same key returns the saved first response, including a 500, and different parameters on the same key return an error. Keys can be up to 255 characters, Stripe suggests V4 UUIDs, and they can be pruned after at least 24 hours. Tell Claude to generate one key per logical operation, not one per attempt.

Common mistakes

  • Retrying every 429. On a spend cap, Anthropic says retries, including the SDK's automatic ones, fail until access resumes, so that case needs an alert.
  • Matching on error message text. Anthropic's docs say to catch the SDK's typed classes, handling the most specific first.
  • Checking only the status code on a stream, where the docs say an error can arrive after a 200.
  • Leaving the 10-minute default timeout on a request someone is waiting for. Timed-out requests are also retried twice by default, so the wait can be longer still.

Sources

Checked 6 November 2026. Products change often, so confirm details with the vendor.

Related

Beyond the course