Production failures

anthropic api 529 overloaded_error

Reproduction script · anthropic-529-retry-budget.py · updated 2026-08-06

If you are reading that a 529 means you have been rate-limited and need to slow down, that is the wrong number in your head. 429 is your account's rate limit. 529 is overloaded_error: the API is temporarily out of capacity, it is not about your quota, and it is retryable. It matters which one you are looking at, because the two demand opposite responses: a 429 says throttle yourself, a 529 says back off and retry the exact same request. The reported failures on this page are almost never the API being down. They are a retry that did not happen, a retry budget too small for the load you created, or a 529 mislabelled as a 429 so nobody handled it.

The symptom

The error, verbatim from a reported run:

API Error: 529 {"type":"error","error":{"type":"overloaded_error","message":"Overloaded"},"request_id":"req_011CZbe5iJ3VQtjAKPLD26Y1"}

Read the type, not the prose. The HTTP status is 529 and the inner error.type is overloaded_error. That pair is the whole diagnosis, and it is what tells overloaded_error apart from the two errors people confuse it with:

What you seeWhat it meansWhat it asks of you
429 rate_limit_errorYour account exceeded RPM/TPM. Carries a retry-after headerSlow your own request rate; respect retry-after
500 api_errorA generic server faultRetry with backoff
529 overloaded_errorThe service is temporarily at capacity. Not your quotaBack off with jitter and retry; the request is fine

The number is stable across surfaces. You get the same 529 overloaded_error from a raw POST /v1/messages, from the Python and TypeScript SDKs, from a Managed Agents session, and from every framework built on top. That is why searching the string returns hits from repositories you have never used.

One trap the message hides: in the SDK's typed exceptions, 529 is a 5xx, so it surfaces as InternalServerError (the same class as a 500), not as RateLimitError. If your handler branches on the exception class alone, a 529 lands in your generic server-error path. Branch on error.type == "overloaded_error" when you need to treat it distinctly from a plain 500.

What causes it

A client that never retried, or a wrapper that ate the retry. This is the single most common shape, and it is worth stating plainly because it inverts the intuition: the official Python and TypeScript SDKs already retry 529. The default is max_retries=2, which retries 408/409/429/5xx and connection errors with exponential backoff, so a bare SDK call makes up to three attempts on an overload before it raises. When a report says "no retry, no backoff, the session dies immediately," the retry was disabled, set to zero, or swallowed by a layer wrapping the SDK. A third-party agent framework that catches the exception and terminates the turn will surface a first-attempt 529 as a hard failure while the SDK underneath was ready to retry.

A retry budget too small for the load you created. Two retries is enough for an isolated blip. It is not enough for a sustained overload window that you are feeding yourself. The artifact on this page models exactly this: fire 64 requests at an endpoint that can serve 8 per tick, give each request the SDK's default of three attempts, and 40 of the 64 are dropped as hard 529s regardless of the backoff shape. The budget, not the backoff curve, is the binding constraint at that width.

Fan-out is the trigger you actually control. No editor publishes its real 529 rate under load, and this page does not pretend to know it. What the reported cases show clearly is when it fires: subagent spawns and parallel fan-out. One report has two back-to-back planner subagents on Opus both returning 529 before falling back to a smaller model. Another describes a six-plus parallel-subagent fan-out where a single 529 cascades and loses in-flight work across the whole batch, and even reaches unrelated sessions on other machines. When an orchestrator spawns N agents in one burst, it is N nearly simultaneous requests hitting the same capacity at the same instant. You built the spike.

Synchronised retries amplify the spike. Backoff without jitter is worse than it looks. Every request that fails on the same tick retries on the same later tick, so the fleet moves in lockstep and re-collides as a wave. In the artifact, exponential-no-jitter takes 127 ticks and 288 total attempts to drain a burst that full jitter clears in 14 ticks and 225 attempts. Every extra attempt is more load pushed back onto the endpoint you are waiting on. A retry storm and a retry convoy are both failures of the same missing ingredient.

The 529 is mislabelled or never logged. In one reported case the 529 renders in the UI as "Rate limited," which reads as a 429 quota problem and sends the operator to the wrong fix, and the structured error buffer comes back empty because the 529 was only ever rendered as text. If your telemetry cannot tell you the type and request_id of the errors you hit, you cannot tell an overload from a throttle from an outage, and every one of them looks like "the API is flaky."

Telling it apart

Before you touch backoff constants, answer three questions in order.

Is it a 529 or a 429? Read the status and the error.type. If it is rate_limit_error, the fix is on your side of the meter: you are over your RPM or TPM, respect retry-after and reduce your own rate. If it is overloaded_error, no amount of slowing your average rate changes the fact that a burst momentarily exceeded shared capacity. Do not apply the 429 remedy to a 529.

Is anything already retrying? Find out how many attempts each failing request actually made. If the answer is one, retry is off or a wrapper is intercepting the exception before the SDK's own retry runs, and your job is to stop swallowing it, not to hand-roll a new loop. If the answer is already two or three and you are still seeing drops, the budget is too small for your load and the next section applies.

Does it only happen at high fan-out? A 529 that appears only when your orchestrator spawns many agents at once, and never on a single sequential call, is not the API being unreliable. It is your concurrency profile. That distinction decides whether you fix the retry policy, the concurrency, or both. The same third-month cost dynamic sits behind it as the LangGraph recursion loop: work that fans out multiplies the requests, and the multiplied requests are what tip capacity.

The fix

The order is deliberate, because the artifact shows the levers do not all pull the same weight.

Raise the retry budget first. At three attempts the backoff shape is irrelevant: in the artifact, fixed, exponential and jittered backoff all drop the same 40 of 64. The budget is the survival line. Set max_retries to a value that reflects how long an overload window can plausibly last for your traffic, not the default two. In the model, moving from three attempts to eight is the difference between dropping 40 tasks and dropping none.

Then add full jitter. Once the budget can drain the burst, jitter is what makes it cheap. Full jitter (sleep(random.uniform(0, base * 2 ** attempt))) drains the same 64-request burst in the fewest total attempts, because it keeps the served slots full every tick instead of arriving in colliding waves. If you are wrapping the SDK's retry with your own, jitter is the one thing you must not omit.

Cap the concurrency of your fan-out. The cheapest 529 is the one you never provoke. Put a semaphore or a queue in front of subagent spawns so you release N requests over a short window rather than all at once. A burst of 64 that arrives as eight waves of eight never triggers the overload the single burst does. This is the lever the retry policy cannot reach, because it changes the spike itself.

Handle 529 distinctly from 429. Branch on error.type. On rate_limit_error, respect retry-after and back your own rate off. On overloaded_error, retry with jittered backoff and, if it persists, consider routing the retry to a less loaded model (a smaller model is often available when the largest is saturated). Never render one as the other.

Make it observable. Log the status, the error.type, and the request_id for every failure into structured telemetry, not just the UI. You cannot budget a retry policy against a failure mode you cannot count.

Verifying the fix

Run the artifact and read the two tables. It needs no key, no model and no network, so it isolates the retry dynamics from the provider entirely. Confirm the shape of your own outage matches: if you are dropping requests at three attempts, raising the budget is the first move, and the table tells you by how much.

Force your retry budget to one and confirm the drops appear. This proves your retry path is actually wired. It is the step people skip, and it is the reason most "we already retry" reports exist: the retry was configured on an object that the hot path never used. If a budget of one does not change your drop rate, your budget of eight was never applied either.

Log the attempt count and error.type for a week under real fan-out. The number to watch is not the average 529 rate; it is the drop rate at your peak concurrency, because that is where the burst lives. If the maximum attempts-per-request climbs while your traffic is flat, you have an overload window that is outlasting your budget, and you widen the budget or narrow the fan-out before it finds your ceiling.

Sources

Every claim here comes from either a run of the artifact or a reported case listed in the page's sources field: the subagent-spawn 529 with no exponential backoff and its request IDs, the case where a 529 is rendered as "Rate limited" and never written to the structured error buffer while a six-plus agent fan-out loses in-flight work, the transient 529 that aborts long-running tasks with no auto-recovery, the persistent 529 that is silently retried with no output, the repeated-529 retry threads, the request for auto-retry in interactive mode, the raw 529 bug report, and a third-party framework that terminates the conversation on overloaded_error instead of retrying.

The SDK retry defaults (max_retries=2, retrying 408/409/429/5xx and connection errors with exponential backoff) and the 429 versus 529 versus 500 distinction are from the Anthropic API error and client-configuration reference. The drop and attempt counts are produced by the artifact on this page, which models the retry dynamics of a fan-out against a capacity-limited endpoint. It does not measure Anthropic's capacity or real 529 rate, and neither does this page.

Reported cases

Leave your email and we come back to you.