Skip to content

Guide

Anthropic 529 "overloaded" errors: what they mean and how to fail over

A 529 overloaded_error means Anthropic's API is temporarily overloaded across all users, not that you hit your own limit: retry once after a short, jittered wait, then send the request to another provider or a tested model. In a stream the same overload arrives as an error event after the 200, so take back any partial answer before you start again elsewhere.

By INFRO Editorial

Last updated

Last checked

On this page
  1. What a 529 means, and what it does not
  2. What the SDK does already
  3. Retry once, then fail over
  4. The overload that arrives mid-stream
  5. Knowing it is Anthropic, not you
  6. What to do, case by case
  7. The same failover through INFRO
  8. Questions
  9. Sources

What a 529 means, and what it does not

Anthropic documents 529 overloaded_error as "the API is temporarily overloaded", and says it can occur when the API sees high traffic across all users. It is about Anthropic's capacity, not your account. The body has the same shape as every Anthropic error:

529 response body
{
  "type": "error",
  "error": { "type": "overloaded_error", "message": "Overloaded" },
  "request_id": "req_..."
}

Three neighbouring errors look similar and need the opposite response:

Status and typeMeansRetry?Fail over?
529 overloaded_errorAnthropic is overloaded for everyoneOnce, brieflyYes
429 rate_limit_error with retry-afterYour organization's rate limitAfter retry-afterYes, if a user is waiting
429 with error.details.error_code enforced_spend_limit_reachedYour tier's monthly spend cap; no retry-afterNoNo
400 invalid_request_error, "You have reached your specified API usage limits"A spend limit you set on the organization or workspaceNoNo
500 api_errorAn error on Anthropic's sideOnce, with backoffYes
From Anthropic's errors and rate-limits pages.

A spend limit you set yourself arrives as a 400, not a 429. Code that treats every 400 as a malformed request, or every 429 as a rate limit, gets both of these wrong.

What the SDK does already

Anthropic's SDKs retry transient failures, including 529, twice by default with exponential backoff, honouring retry-after. During a real overload that is three requests to a struggling API before your code sees anything, while the user waits. Where you have somewhere else to send the request, set maxRetries: 0 (max_retries=0 in Python) and decide yourself: one short retry, then fail over.

Rate-limit standing is on every response, in anthropic-ratelimit-requests-*, anthropic-ratelimit-tokens-*, anthropic-ratelimit-input-tokens-* and anthropic-ratelimit-output-tokens-* headers (limit, remaining, reset). They tell you about your limits; they cannot predict a 529.

Retry once, then fail over

This reads the error type, retries a 529 once after a jittered wait, and then answers from OpenAI. It refuses to route around either kind of spend limit.

import Anthropic from "@anthropic-ai/sdk";
import OpenAI from "openai";

// SDK retries off: by default they would retry a 529 twice against the same
// overloaded API before your code sees it. The loop below decides instead.
const anthropic = new Anthropic({ maxRetries: 0, timeout: 30_000 });
const openai = new OpenAI({ maxRetries: 0, timeout: 30_000 });

// The error type Anthropic sent, e.g. "overloaded_error" or "rate_limit_error".
function errorType(err: InstanceType<typeof Anthropic.APIError>): string | undefined {
  const body = err.error as { error?: { type?: string } } | undefined;
  return err.type ?? body?.error?.type;
}

// A tier spend cap is a 429 that waiting cannot fix.
function isSpendCap(err: InstanceType<typeof Anthropic.APIError>): boolean {
  const body = err.error as { error?: { details?: { error_code?: string } } } | undefined;
  return body?.error?.details?.error_code === "enforced_spend_limit_reached";
}

export function canFailOver(err: unknown): boolean {
  if (err instanceof Anthropic.APIConnectionError) return true; // network or timeout
  if (!(err instanceof Anthropic.APIError)) return false;
  if (errorType(err) === "overloaded_error") return true; // 529, or mid-stream
  if (err.status === 429) return !isSpendCap(err);
  // 400 includes a spend limit you set yourself: never route around it.
  return err.status !== undefined && err.status >= 500;
}

const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));

export async function answer(prompt: string): Promise<{ text: string; servedBy: string }> {
  // One short retry on Claude: a 529 is often brief. Then fail over.
  for (let attempt = 0; attempt < 2; attempt++) {
    try {
      const res = await anthropic.messages.create({
        model: "claude-sonnet-5-5",
        max_tokens: 1024,
        messages: [{ role: "user", content: prompt }],
      });
      const text = res.content.map((b) => (b.type === "text" ? b.text : "")).join("");
      return { text, servedBy: "anthropic" };
    } catch (err) {
      if (!canFailOver(err)) throw err;
      if (attempt === 0) await sleep(250 + Math.random() * 500);
    }
  }
  const res = await openai.chat.completions.create({
    model: "gpt-5.4-mini",
    messages: [{ role: "user", content: prompt }],
  });
  return { text: res.choices[0]?.message.content ?? "", servedBy: "openai" };
}

try {
  const { text, servedBy } = await answer("Summarize this support thread in two lines.");
  console.log(`[${servedBy}] ${text}`);
} catch (err) {
  if (!(err instanceof Anthropic.APIError)) throw err;
  console.error(`not retried: ${err.status} ${errorType(err)} (request ${err.requestID})`);
  process.exitCode = 1;
}
Tested: one 529 is retried on Claude; two fail over to OpenAI; the tier spend cap (429) and your own spend limit (400) are neither retried nor failed over.

The overload that arrives mid-stream

With stream: true the response can start with a 200, send some text, and then end with an error event. Anthropic's streaming docs show it in this form:

An overload during a stream
event: error
data: {"type": "error", "error": {"type": "overloaded_error", "message": "Overloaded"}}

Both SDKs raise it as an error while you iterate the stream, but there is no HTTP status to read: in TypeScript the error's type is overloaded_error and status is undefined; in Python it is a status error on a 200 response whose body names the type. The rule is the one every streaming failover follows: never continue a half-written answer with another model. Take the partial text back, tell the user, and start again elsewhere.

import Anthropic from "@anthropic-ai/sdk";
import OpenAI from "openai";

const anthropic = new Anthropic({ maxRetries: 0 });
const openai = new OpenAI({ maxRetries: 0 });

// Stand-ins for your UI: show text as it arrives, and take it back.
let onScreen = "";
const show = (text: string) => (onScreen += text);
const retract = () => {
  console.log(`partial answer discarded: ${JSON.stringify(onScreen)}`);
  onScreen = "";
};

async function streamFromClaude(prompt: string) {
  const stream = await anthropic.messages.create({
    model: "claude-sonnet-5-5",
    max_tokens: 1024,
    stream: true,
    messages: [{ role: "user", content: prompt }],
  });
  // An overloaded_error can arrive here, after the 200 and some text.
  for await (const event of stream) {
    if (event.type === "content_block_delta" && event.delta.type === "text_delta") show(event.delta.text);
  }
}

const prompt = "Explain this invoice line by line.";
try {
  await streamFromClaude(prompt);
  console.log(`[anthropic] ${onScreen}`);
} catch (err) {
  // Mid-stream errors have no HTTP status; the type says what happened.
  const retryable =
    err instanceof Anthropic.APIConnectionError ||
    (err instanceof Anthropic.APIError && (err.type === "overloaded_error" || (err.status ?? 0) >= 500));
  if (!retryable) throw err;
  // Never continue a half-written answer with a different model: the two
  // will not join up. Take the partial text back and start again elsewhere.
  if (onScreen) retract();
  const res = await openai.chat.completions.create({
    model: "gpt-5.4-mini",
    messages: [{ role: "user", content: prompt }],
  });
  console.log(`[openai] ${res.choices[0]?.message.content ?? ""}`);
}
Tested against a stream that sends a 200, some text, then overloaded_error: the partial answer is discarded and OpenAI answers. A stream that completes stays on Claude.

Knowing it is Anthropic, not you

Anthropic's status page, status.claude.com, lists the Claude API (api.anthropic.com) as its own component and offers Atom and RSS feeds plus email, Slack and webhook subscriptions. Subscribe a webhook or the Atom feed to your incident channel. Your own signal comes first, though: alert when the share of 529 responses (and mid-stream overloaded_error events) for one model passes a few percent over five minutes, and log the request-id header Anthropic returns on every response, which is what their support will ask for.

What to do, case by case

Retry once, after 0.25–0.75 s
if a single 529 or 500 arrives and the user can wait a second.
Fail over
if the retry also fails, or a user-facing request cannot wait.
Discard and restart elsewhere
if overloaded_error arrives after part of a streamed answer was shown.
Wait retry-after
if it is a 429 rate_limit_error that carries the header.
Stop and alert
if the 429 carries enforced_spend_limit_reached, or a 400 says you reached your usage limits.

Questions

What does Anthropic error 529 overloaded mean?
Anthropic's API is temporarily overloaded, which can happen when it sees high traffic across all users. It is not your rate limit or spend limit. Retry once after a short wait, then fail over.
Is a 529 the same as a 429?
No. A 429 is your organization's rate limit (or, without retry-after, your tier's spend cap). A 529 is Anthropic's capacity. A spend limit you set yourself returns 400.
Does the Anthropic SDK retry 529 errors?
Yes. It retries transient failures, including 529, twice by default with exponential backoff. Set max retries to 0 where you would rather fail over immediately.

Sources

Every statement about another company on this page comes from that company's own page, opened on the date shown. Prices and defaults change; check the source before you decide.

  1. 1.platform.claude.com/docs/en/api/errors (opens in a new tab) — checked Oct 24, 2026.
    • Anthropic returns 529 overloaded_error when the API is temporarily overloaded.
    • Anthropic says a 529 can occur when the API sees high traffic across all users, not only yours.
    • Anthropic errors are JSON with a top-level type of "error", an error object with type and message, and a request_id.
    • Anthropic's SDKs retry transient failures twice by default with exponential backoff, honouring retry-after.
  2. 2.platform.claude.com/docs/en/build-with-claude/streaming (opens in a new tab) — checked Oct 24, 2026.
    • In a stream, Anthropic can send an overloaded_error event after the 200 response has started, where a non-streaming request would have received a 529.
  3. 3.platform.claude.com/docs/en/api/rate-limits (opens in a new tab) — checked Oct 24, 2026.
    • A 429 from Anthropic may carry retry-after, the seconds to wait; the tier spend-cap 429 never does.
    • Anthropic responses carry anthropic-ratelimit-requests-*, -tokens-*, -input-tokens-* and -output-tokens-* headers (limit, remaining, reset).
    • When an organization or workspace spend limit you set is reached, Anthropic returns 400 invalid_request_error, not 429.
  4. 4.status.claude.com (opens in a new tab) — checked Oct 24, 2026.
    • Anthropic's status page, status.claude.com, lists the Claude API (api.anthropic.com) as its own component and offers Atom and RSS feeds plus email, Slack and webhook subscriptions.

The team building INFRO, a BYOK-first control plane for production AI. Articles are written from the engineering work on the gateway and cite their external sources.