How to fix Claude API 429 and overloaded errors
What 429 rate_limit_error, overloaded_error and 402 mean when you call Claude, which ones to retry, and how to stop hitting them with pooled capacity.
You start a batch job or a fleet of agents on Claude, and some requests come back with 429 rate_limit_error, "rate limit exceeded", or an overloaded_error partway through a stream. Some of these errors are worth retrying, some mean your own limits did their job, and one means you are out of credit. This guide explains each error as Lovely Router returns it, then builds a Python client that retries the right ones, with an Anthropic API retry on 429 that waits for retry-after, and stays under its limits.
What each error means
Through Lovely Router, a request passes three checks before it reaches Claude: your balance and the key's spend limit, the rate and concurrency limits you set on the key, and the capacity of the channels serving the model. Each check has its own error, in Anthropic's error format so the SDK raises its usual exceptions:
| Status | Anthropic error.type | Message | Cause | Retry? |
|---|---|---|---|---|
429 | rate_limit_error | This API key has reached its rate or concurrency limit. | Your key's requests-per-minute or concurrency limit. Has retry-after. | Yes, after retry-after |
429 | rate_limit_error | All upstream capacity for this model is busy. Retry shortly. | Every channel for the model stayed full for 10 seconds. Has retry-after. | Yes, after retry-after |
429 | rate_limit_error | Upstream capacity for this model is busy. Retry shortly. | Every channel tried reported a rate limit. | Yes, with backoff |
502 | api_error | The model provider returned an error. Please retry. | Every channel tried failed. | Yes, with backoff |
402 | billing_error | Insufficient balance. Top up at the dashboard. or This API key has reached its spend limit. | Balance at or below zero, or the key's spend limit. | No. Add credit or raise the limit. |
Clients that call Claude in OpenAI format see rate_limit_exceeded for the same 429, and Gemini format uses RESOURCE_EXHAUSTED.
What about 529 overloaded? Anthropic's own API answers 529 overloaded_error when it is under load. Through Lovely Router an overloaded channel is not the end of the request: the gateway retries it on another channel, and you see a 429 or 502 only if every attempt fails. The documented status codes have no 529; treat any other 5xx like 502. Once a stream has started, a busy channel arrives as an overloaded_error event inside the stream instead, because the 200 status has already been sent.
None of these cost money. A request rejected with 429 is not charged, queued requests are charged only when they run, and requests that fail with an error are not charged.
Why you see fewer of them through a gateway
One provider account stops at its own rate limits. Lovely Router serves each model from a pool of channels in a channel group, admits your requests against their combined capacity, and handles most trouble before it reaches you:
When the channel a request would use is full, the gateway tries the others. When all are full, the request waits up to 10 seconds for the first one to free up. An admitted request carries x-lovely-queued-ms with the time it waited.
A channel that times out or returns 408, 409, 425, 429 or a 5xx is replaced by another channel, up to three attempts per request. A stream that fails before its first token is retried the same way, so you get a clean stream or an ordinary HTTP error.
A channel that errors more or answers much more slowly than usual gets fewer new conversations until it recovers.
High-concurrency LLM apps covers this in depth, and the status page shows each channel group's live success rate and latency. A 429 or 502 that reaches you has already lasted through several attempts, so your client should back off rather than hammer.
Walkthrough: a Claude client that retries the right errors
Raise the SDK's retries
The Anthropic SDK already retries
408,409,429and5xxresponses with exponential backoff and honorsretry-after. It does so twice by default. For batch jobs, raisemax_retries:Pythonimport os import anthropic client = anthropic.Anthropic( base_url="https://lovelyrouter.com", api_key=os.environ["LOVELY_API_KEY"], max_retries=5, # default is 2 )Handle what is left
After the retries run out, the SDK raises. Catch the classes you treat differently, and log the request id so you can look the call up in Logs or quote it to support.
Pythondef ask(prompt): try: message = client.messages.create( model="claude-sonnet-5.5", max_tokens=1024, messages=[{"role": "user", "content": prompt}], ) except anthropic.RateLimitError as e: # 429 after every retry print("429:", e.message, "| retry-after:", e.response.headers.get("retry-after"), "| request id:", e.response.headers.get("x-lovely-request-id")) raise except anthropic.APIStatusError as e: if e.status_code == 402: # balance or spend limit: retrying won't help print("402:", e.message) raise return next(block.text for block in message.content if block.type == "text")Cap your own concurrency
A worker pool sized below the key's concurrency limit keeps a batch from tripping it at all:
Pythonfrom concurrent.futures import ThreadPoolExecutor prompts = [f"Summarize ticket {i} in one line." for i in range(200)] with ThreadPoolExecutor(max_workers=8) as pool: answers = list(pool.map(ask, prompts))
Without an SDK, the same policy fits in one flag. --retry covers 429 and 5xx and honors retry-after:
curl --retry 5 --retry-max-time 120 https://lovelyrouter.com/v1/messages \
-H "x-api-key: $LOVELY_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{"model": "claude-sonnet-5.5", "max_tokens": 1024,
"messages": [{"role": "user", "content": "Hi"}]}'For your own retry loop, follow the Errors policy: wait retry-after when present, otherwise 1, 2, 4, 8 seconds capped at 30 plus up to a second of jitter, and stop after about five attempts.
Set limits on your own keys
Each key can have a Requests per minute limit (rolling 60 seconds) and a Max concurrent requests limit (open streams count until they end). Both are off by default; set them under Limits & restrictions in API keys. A request over a limit waits up to 2 seconds for room, then fails with 429 and a retry-after header.
Give each workload its own key: production, a nightly batch and an eval run then can't starve each other, and a runaway loop hits its own key's ceiling instead of your app's. API keys covers every key setting.
Spend limits and 402
Every request checks your balance and the key's spend limit before it runs. The spend limit is a lifetime cap on what the key may spend across model requests, tool runs and browser runs, which makes it a good guard on unattended agents and CI jobs. When either is exhausted, you get 402 with billing_error. Don't retry it: add credit on Billing or raise the key's limit. A request that started with a positive balance always finishes, so the balance can end slightly below zero; the next top-up covers it.
Pitfalls
402, 400 or 404The same request fails the same way. Fix the request, the key or the balance first.
Five attempts in your own loop, each an SDK call with max_retries=5, can send 30 requests for one answer. Retry in one layer.
A request may wait up to 10 seconds for capacity, and streams start with their first token. Allow at least 30 seconds before the response starts.
Output streamed before the error is charged. Retry only if you need the whole answer, and keep or drop the partial text deliberately.
Without jitter, every worker retries at the same moment and collides again.
Frequently asked questions
What does "rate limit exceeded" mean on the Claude API?+
It is a 429. Through Lovely Router it means either your key reached the requests-per-minute or concurrency limit you set, or every channel serving the model stayed busy. The message tells you which, and both are safe to retry after the retry-after delay.
Is overloaded_error caused by my requests?+
No. It means the channel serving the model is busy, the condition Anthropic's own API reports as 529 overloaded_error. The gateway retries overloaded channels for you before a stream starts, so you normally see overloaded_error only as an event inside a stream that had already begun. Retry that request from the start.
Am I charged for requests that fail with 429?+
No. A request rejected with 429 is never charged, queued requests are charged only once they run, and failed requests cost nothing. A stream that breaks partway is charged for the output already delivered.
How many times should I retry a 429?+
About five times, waiting for retry-after when it is present and otherwise backing off exponentially up to 30 seconds with jitter. The gateway has already retried across channels, so a 429 that survives five client attempts means you should slow down or raise your key's limits.
Why do I get 402 instead of 429?+
402 is about money, not speed: your balance is at or below zero, or the key reached its spend limit. Add credit or raise the limit; retrying alone won't help.
Next, read Rate limits & failover for every status code, the Claude API page for models and prices, or Claude prompt caching to cut the cost of the requests you do send. Pricing explains the prepaid balance.