Error reference

Anthropic 529 overloaded_error: What It Means and How to Handle It

Updated July 27, 2026

In short
HTTP 529 overloaded_error from the Anthropic API means Anthropic-side capacity is temporarily exhausted. It is not your quota, so requesting a limit increase changes nothing. Retry the same request with exponential backoff plus jitter, and fail over to another model or provider when the retries run out. A 429 rate_limit_error is the opposite case: that is your own organization budget, and the retry-after header says exactly how long to wait.
start here
client = Anthropic(max_retries=5)  # SDK retries 429, 5xx and 529 with backoff
Diagnosis

Causes at a glance

CauseHow to recognize itFix
Anthropic-side capacity exhaustedHTTP 529 with error.type overloaded_error; unrelated to your usage numbersRetry with exponential backoff and jitter; fail over after a bounded number of attempts
Your own organization rate limitHTTP 429 with error.type rate_limit_error and a retry-after headerWait the retry-after interval, smooth traffic, then request higher limits if it persists
Retry storm amplifying the outage529s cluster on a fixed interval and get worse right after a deployUse full jitter and cap concurrent in-flight retries so workers stop resynchronising
Large uncached prompts held on every callusage.cache_read_input_tokens is 0 on every response despite a stable prefixAdd cache_control to the stable prefix: big cut in input tokens, cost, and latency
Bulk work running on the synchronous API529s only during backfills or evals, never on interactive trafficMove it to the Message Batches API: separate queue, 50% cheaper

529 versus 429: whose limit did you actually hit?

Anthropic returns HTTP 429 rate_limit_error when your organization exceeds its own requests-per-minute or input/output tokens-per-minute budget, and HTTP 529 overloaded_error when Anthropic itself is temporarily at capacity. The bodies are what distinguish them: read error.type, not just the status code.

That difference decides who can fix it. A 429 is yours to manage: smooth the traffic, or raise the limit. A 529 is not about you at all, so a limit increase is useless; the only correct responses are patient retries and a fallback path. Treating every 529 as a quota problem sends teams chasing a limit increase that would not have helped.

# 429 — your budget
{"type":"error","error":{"type":"rate_limit_error","message":"Number of request tokens has exceeded your per-minute rate limit"}}

# 529 — Anthropic capacity
{"type":"error","error":{"type":"overloaded_error","message":"Overloaded"}}
Step 1

Step 1: classify the error before you retry

Use the SDK exception classes rather than string-matching the message. In the Python SDK a 429 raises RateLimitError and any status at or above 500 (including 529) raises InternalServerError; check status_code or the .type property to separate a plain 500 from an overload.

Catch the most specific class first and let genuinely non-retryable errors (400, 401, 404) propagate immediately instead of being swallowed by a broad handler.

import anthropic

client = anthropic.Anthropic(max_retries=0)  # handle retries explicitly

try:
    msg = client.messages.create(
        model="claude-sonnet-4-5", max_tokens=1024, messages=messages
    )
except anthropic.RateLimitError as e:            # 429 — your own limit
    wait = float(e.response.headers.get("retry-after", "60"))
except anthropic.InternalServerError as e:       # 5xx, including 529
    overloaded = e.status_code == 529 or e.type == "overloaded_error"
except anthropic.APIConnectionError:
    pass  # never reached the API at all
Step 2

Step 2: retry with exponential backoff and full jitter

The Anthropic SDKs already retry connection errors, 408, 409, 429, and 5xx (529 included) with exponential backoff; max_retries defaults to 2. Raising it to 4 or 5 absorbs most transient overloads with no other change.

When you write the loop yourself, use full jitter: sleep a random duration in the window rather than the full backoff interval. Fixed backoff makes every throttled worker retry at the same instant, which recreates the overload at each step. Bound total attempts as well: an unbounded retry against a saturated service is a denial-of-service you inflict on yourself.

import random, time
import anthropic

def with_backoff(fn, attempts=6, base=1.0, cap=60.0):
    for i in range(attempts):
        try:
            return fn()
        except (anthropic.RateLimitError, anthropic.InternalServerError) as e:
            if i == attempts - 1:
                raise
            # full jitter: sleep anywhere in [0, min(cap, base * 2**i)]
            time.sleep(random.uniform(0, min(cap, base * (2 ** i))))

msg = with_backoff(lambda: client.messages.create(
    model="claude-sonnet-4-5", max_tokens=1024, messages=messages
))
Step 3

Step 3: cut input tokens with prompt caching

Prompt caching stores a stable prefix (a long system prompt, tool definitions, a retrieved document) so later requests reuse it instead of reprocessing it. Cache reads are billed at roughly a tenth of the base input rate, and writes at about 1.25x, so the break-even is around two requests on the five-minute TTL. Smaller requests also finish faster, which reduces exposure to capacity blips.

Caching is a prefix match, so anything volatile placed early in the prompt silently invalidates it. Keep timestamps, request IDs, and per-user context after the cache breakpoint, and verify with usage.cache_read_input_tokens: a persistent zero means something in the prefix changes on every call.

resp = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=1024,
    system=[{
        "type": "text",
        "text": LONG_STABLE_PREFIX,           # keep this byte-identical
        "cache_control": {"type": "ephemeral"},
    }],
    messages=messages,                        # volatile content goes here
)
print(resp.usage.cache_read_input_tokens)     # 0 = nothing was reused
Step 4

Step 4: add cross-provider fallback routing

Backoff buys seconds; a fallback buys availability. Keep an ordered list of deployments (a second Anthropic model, the same model on a different platform, or another vendor entirely) and walk it when the primary returns 529 after its retry budget is spent.

Two rules keep fallback honest. Fail over only on capacity and overload errors, never on a 400 or 401 that will fail identically everywhere. And record which provider actually served each request: a silent fallback changes cost, latency, and output characteristics without anyone noticing until a bill or an eval score moves.

ROUTES = [
    ("anthropic", "claude-sonnet-4-5"),
    ("anthropic", "claude-haiku-4-5"),   # cheaper, usually less contended
    ("openai", "gpt-4o-mini"),           # different vendor, different capacity
]

def complete(messages):
    last = None
    for provider, model in ROUTES:
        try:
            return call(provider, model, messages), provider, model
        except (anthropic.InternalServerError, anthropic.RateLimitError) as e:
            last = e                     # capacity problem: try the next route
            continue
    raise last
Step 5

Step 5: take bulk work off the synchronous API

The Message Batches API accepts up to 100,000 requests per batch, returns results within 24 hours (most finish inside an hour), and costs 50% less per token. It runs on its own queue, so it does not compete with your interactive traffic.

Results come back in arbitrary order, so key them by custom_id rather than position. Evaluations, dataset labelling, document enrichment, and nightly summarisation all belong here: moving them off the synchronous path removes a large share of the requests that were meeting 529s in the first place.

batch = client.messages.batches.create(requests=requests)

while True:
    batch = client.messages.batches.retrieve(batch.id)
    if batch.processing_status == "ended":
        break
    time.sleep(60)

for result in client.messages.batches.results(batch.id):
    if result.result.type == "succeeded":
        store(result.custom_id, result.result.message)
Beyond the one-off fix

Fallback routing is what keeps a 529 from becoming an outage, and it is also the moment your cost model quietly changes, because a different model at a different price served the request. Nexus records every agent action and token_usage event at the runtime-hook level, so each fallback is attributable: which agent, which repo, which provider took over, and what the switch cost against the baseline. The same capture surfaces providers nobody sanctioned, so a fallback added during an incident does not become permanent shadow AI.

Explore Swfte Nexus

Common questions

What does overloaded_error mean in the Anthropic API?
It means Anthropic's own infrastructure is temporarily at capacity and cannot accept your request right now. It is returned as HTTP 529 and has nothing to do with your organization's rate limits or billing, so the fix is retrying with backoff and having a fallback route, not requesting a higher limit.
Is an Anthropic 529 the same as a 429 rate limit?
No. A 429 `rate_limit_error` means your own organization exceeded its requests-per-minute or tokens-per-minute budget and comes with a `retry-after` header. A 529 `overloaded_error` is Anthropic-side capacity, affects requests regardless of your usage, and cannot be resolved by raising your limits.
How should I retry a 529 from Claude?
Retry the identical request with exponential backoff and full jitter, capped at around a minute and bounded to a handful of attempts. The official SDKs do this automatically for 429 and 5xx responses: raising `max_retries` from the default of 2 to 4 or 5 absorbs most transient overloads without any custom code.
Does prompt caching help with 529 errors?
Indirectly, and substantially. Caching a stable prefix cuts the input tokens each request has to process, so calls are cheaper and finish faster, which shrinks the window in which a capacity blip can hit them. Verify it is working by checking that `usage.cache_read_input_tokens` is non-zero on repeat requests.
Should I fail over to another provider on a 529?
Yes, once your retry budget for that request is spent, but only for capacity and overload errors, never for a 400 or 401 that will fail the same way everywhere. Log which provider and model actually served each request, because a silent fallback changes cost, latency, and output quality with no other visible signal.