API Error (Connection error.) · Retrying in 1 seconds… (attempt 1/10)
The label in parentheses is the whole diagnosis: the request produced no HTTP
response at all. There is no status code, no error.type, and no request_id,
which rules out the four things people reach for first — a 429 rate limit, a 529
overload, an authentication rejection and a billing block. Every one of those
arrives as a response and gets labelled with its status in this same banner. A
retry counter is also not evidence that you are being throttled, which is the
most common misreading of the line.
Data as of 2026-09. Vendor limits and defaults change; check the official docs for current values before acting on any number below.
The banner is a classification verdict, and it has already ruled things out
Claude Code retries transient failures up to ten times with exponential backoff before showing you a terminal error. The important part is not the ten — it is that the retry list is selective, and the documented exclusions are specific.
TLS certificate validation failures are reported on the first attempt, with no retries. So are failures arriving after Claude has already completed a block of text or a tool call, because re-running those could execute the same tool calls twice. Neither category ever produces an attempt counter.
Follow that through and the banner is doing free work for you. Seeing
attempt 1/10 at all has already eliminated a certificate problem, and told you
the failure landed before Claude committed to any output. Two of the most
expensive branches in a normal connection-error investigation — corporate TLS
inspection, and a half-finished turn you must not replay — are closed before you
change a single setting. The same string without a counter, failing instantly,
means the opposite and belongs to
TypeError (fetch failed).
It also tells you something about time. Exponential backoff means the intervals grow, so ten attempts do not span ten seconds; they span a window that widens with each retry. Reaching attempt 10 is not ten pieces of bad luck — it is one condition that outlived the entire backoff window. That is a much stronger signal than the banner’s cheerful tone suggests, and it is the moment to stop waiting and start diagnosing.
Whose counter is it
The ten comes from CLAUDE_CODE_MAX_RETRIES, a setting belonging to the CLI. It
is not your SDK’s retry count: the official Anthropic SDKs retry transient
failures twice by default. If you have set max_retries in code somewhere, this
banner is not it and changing that value will not move the numbers you are
watching. The same counter appears on unrelated failures for the same reason —
a 503 with no healthy upstream
walks through what the loop does and does not accomplish.
Two banners that look the same and are not
Confusing these costs people a working session, because the response is opposite in each case.
Retrying in Ns · attempt x/y means a request failed and this is attempt
number x. Waiting for API response · will retry in … · check your network
means no data has arrived for about twenty seconds and the request has not
failed yet — it is still open, and the work may still land. Killing the second
one because it looks like the first throws away a turn that was in progress.
If waiting rather than failing is what you are watching, read
No response from API, retrying in 2m 25s
instead of this page.
Is retrying useful?
Yes — and it is already happening. Your job is to read the sequence, not to start it.
Connection failures of this shape are usually transient, and the built-in loop resolves most of them without you doing anything. Let it run once. What you are watching for is the shape of the sequence, because it is the diagnosis:
- One or two attempts, then the turn completes. Transient. Nothing to fix unless it becomes frequent.
- The counter climbs steadily to the cap on most requests. A stable condition on your path. More attempts will not find a different answer.
- It fires on some requests and not others in the same session. Something is load- or size-dependent rather than broken outright.
The cheap wrong fix is raising the retry count — whether by setting
CLAUDE_CODE_MAX_RETRIES higher or by reaching for the retry watchdog variable
that extends retrying further. If attempts 1 through 10 all failed identically,
attempts 11 through 30 are the same request, over the same path, to the same
resolver. You are buying a longer hang, not a different outcome. The watchdog
exists for capacity errors, where waiting genuinely is the strategy; a
connection error that produced no response is not that.
Telling the causes apart
Does a trivially small request fail the same way? Send the shortest possible prompt. If it fails identically, the failure is independent of your payload and you can stop looking at context size, model choice and attachments entirely.
Does it reproduce on a different network? Phone hotspot, a different machine, a cloud shell. Corporate egress proxies, VPN split tunnels and inspecting middleboxes sit in exactly the position that produces a response-less failure. If the other network is clean, the fault is local to yours.
Did it start after an infrastructure change? A new VPN client, a container base image bump, a DNS resolver change, new egress rules. Suspect the change before you suspect the vendor, and roll it back far enough to prove which side owns the problem.
Are you pointed at a custom base URL or a gateway? Then the connection that failed was to them, not to Anthropic, and no amount of work on your account will help. Send the same request straight at the official endpoint to confirm.
Does /status show the credential you expect? Not because a credential
causes a connection error — it cannot — but because a stray environment variable
routing you through a different base URL or a different provider changes the host
you are failing to reach. This is a five-second check that occasionally ends the
investigation.
Is anyone else seeing it right now? If the failure is general and brief, it is upstream and the answer is to wait. Check the vendor status page before spending an afternoon on your own configuration.
Fix by scenario
- Small requests fail too, on one network only — fix the path: exempt the API host from the inspecting proxy, or route around the VPN. Re-test from the failing network, not the clean one.
- Started after a change — revert the change first and confirm the banner stops. Diagnosing forward from a broken state is slower than proving which edit did it.
- Custom gateway in the path — switch to the direct endpoint to isolate, then take it up with whoever runs the gateway. Keep a one-command way to flip between routes; it turns a two-hour investigation into a two-minute one.
- Intermittent, unrelated to size or network — let the loop absorb it. This is what it is for, and it is already doing it.
- Reporting it — there is no
request_idfor a failure that produced no response, and there never will be. Capture what does exist instead: the exact timestamp with timezone, the base URL actually in effect, whether small requests also fail, and whether a plain request from the same machine reproduces it.
How to confirm it’s fixed
A single successful request proves nothing here, because the loop was already producing successful requests most of the time. Confirm against a full session of ordinary work with no banner at all, then repeat it once. The failure is intermittent by nature, so the absence of one occurrence is not evidence; the absence across a workload that used to produce several is.
If your fix was a route or proxy change, verify it is in effect at runtime rather than in the file you edited — print the base URL and proxy the process is actually using, from a freshly launched session.
Related errors
The neighbours in this cluster are told apart by what survived the failure. If your code caught a typed exception rather than watching a banner, you have anthropic.APIConnectionError: Connection error, and the useful content is the exception’s underlying cause. If the stream was cut after partial output had already arrived, see connection closed mid-response, where the ordering of the 200 explains why no automatic retry applies at all. If the cut came after a measurable quiet interval you can move by editing a number, it is a stream idle timeout. When you are not sure which of them you are holding, the AI coding error triage tool sorts them by the signals used above: whether a response arrived, whether output arrived, and whether a retry counter appeared at all.