Guide

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.

Prepaid, no subscriptionREST or MCPOne key for models, data and agents
lovelyqueue · spreadpool Apool Bpool C429 → retrypool Dpool Epool F

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.

01

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:

StatusAnthropic error.typeMessageCauseRetry?
429rate_limit_errorThis 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
429rate_limit_errorAll 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
429rate_limit_errorUpstream capacity for this model is busy. Retry shortly.Every channel tried reported a rate limit.Yes, with backoff
502api_errorThe model provider returned an error. Please retry.Every channel tried failed.Yes, with backoff
402billing_errorInsufficient 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.

02

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:

Queueing

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.

Failover

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.

Health

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.

03

Walkthrough: a Claude client that retries the right errors

search_toolsrun_toolget_run
  1. Raise the SDK's retries

    The Anthropic SDK already retries 408, 409, 429 and 5xx responses with exponential backoff and honors retry-after. It does so twice by default. For batch jobs, raise max_retries:

    Python
    import os
    import anthropic
    
    client = anthropic.Anthropic(
        base_url="https://lovelyrouter.com",
        api_key=os.environ["LOVELY_API_KEY"],
        max_retries=5,  # default is 2
    )
  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.

    Python
    def 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")
  3. Cap your own concurrency

    A worker pool sized below the key's concurrency limit keeps a batch from tripping it at all:

    Python
    from 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
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.

04

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.

05

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.

06

Pitfalls

Retrying 402, 400 or 404

The same request fails the same way. Fix the request, the key or the balance first.

Stacking retry loops

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.

Timeouts that are too short

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.

Retrying a stream that already produced output

Output streamed before the error is charged. Retry only if you need the whole answer, and keep or drop the partial text deliberately.

Retrying in lockstep

Without jitter, every worker retries at the same moment and collides again.

07

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.

One prepaid key for models, data and agents

No subscription. Top up, use what you need, see every charge in your logs.