Frequent ECONNRESET on large-context Opus 5 (1M) sessions — RSTs originate from server edge, with SACK gaps on upload
Frequent ECONNRESET on large-context Opus 5 (1M) sessions — RSTs originate from the server edge, with SACK gaps on upload
Summary
Persistent Connection dropped (ECONNRESET) · Retrying in Ns · attempt N/10 banners in Claude Code sessions running Opus 5 with the 1M context window. Packet capture shows the RSTs are sent by the server edge, not by the local network, and several of them carry SACK blocks indicating the server was missing multi-segment runs of the uploaded request body.
Retries usually recover, so hard failures are rare in the transcript — but the retry banners are frequent enough to disrupt work, and each one stalls the session for 2–20s.
Environment
- Claude Code 2.1.234, macOS (Darwin 25.5.0), Node v25.6.0
- Model:
claude-opus-5[1m](1M context) - Affected sessions running at ~420k–457k tokens of context
- Client located in South America; endpoint
160.79.104.10resolves ~16 ms / 6 hops away (CDN edge PoP) - Protocol negotiated: HTTP/2
What the packet capture shows
sudo tcpdump -lni any -vv '(tcp[tcpflags] & tcp-rst != 0) or (ip6 and tcp and ip6[53] & 4 != 0)'
Over a ~2 minute window, deduplicated by 5-tuple + seq:
| Direction | Unique RSTs | TTL |
|---|---|---|
| 160.79.104.10:443 → client | ~69 | 58 |
| client → 160.79.104.10:443 | 13 | 64 |
41 distinct connections were reset by the server in those two minutes.
TTL 58 with a 6-hop path (64 − 6 = 58) places the RST origin at the destination edge, not at any local or ISP device.
SACK evidence of lost upload segments
Four of the server-originated RSTs arrived as [R.] carrying SACK blocks:
17:35:35.742069 160.79.104.10.443 > client.56405: Flags [R.],
options [nop,nop,TS val 3957689344 ecr 99375963,nop,nop,
sack 3 {1654801:1702769}{1610001:1615601}{1584801:1608601}]
Reconstructed gaps in what the server received from the client:
| Time | Missing byte ranges | In units of 1400-byte MSS |
|---|---|---|
| 17:35:35 | 1400, 39200 | 1 seg, 28 segs |
| 17:36:00 | 1400, 19600 | 1 seg, 14 segs |
| 17:36:16 | 5600, 40600 | 4 segs, 29 segs |
| 17:36:38 | 1400, 1400 | 1 seg, 1 seg |
Sequence space in flight at those moments: 370 KB – 1.7 MB, consistent with large request bodies from a 400k+ token context.
The losses are runs of consecutive segments, not isolated drops — a tail-drop signature. Rather than waiting for retransmission, the connection is reset.
Local network ruled out
All measured from the affected machine:
- Packet loss to router, ISP CGNAT, and all internal hops: 0% (25 probes each)
- Bandwidth: ~100 Mbps down / ~63 Mbps up, stable; 6 concurrent 12 MB uploads all completed
- Idle timeout: TLS connections to
api.anthropic.comsurvive 420s of total silence (tested 45/90/150/210/300/420s, with and without SO_KEEPALIVE) - IPv4 vs IPv6 under load: 0/30 failures each
- No proxy, no VPN, MTU 1500, no
NODE_EXTRA_CA_CERTSor related env overrides - 15/15 consecutive TLS handshakes to the API succeed when tested in isolation
Possible relevance of HTTP/2
Connections negotiate HTTP/2. A single reset TCP connection tears down every multiplexed stream on it at once, so a session running subagents loses the main agent and its subagents together. This matches the observed pattern: the banner appears simultaneously in sessions that have subagents active, and does not correlate with concurrency across separate Claude Code processes.
Reproduction
Not reliably reproducible with synthetic traffic. Every synthetic test above passed. It occurs only with real Claude Code traffic at high context — which points at the combination of large request bodies and whatever the edge does when one loses a burst of segments.
Note on observability
The retry banners are not written to the session transcript. Only the rare exhausted-retry failures appear in ~/.claude/projects/**/*.jsonl. Analyzing transcripts therefore measures a different and much smaller population than what users actually experience. If retry counts were recorded (even as a per-turn tally), this class of issue would be far easier to quantify from the client side.
Separately: /bug itself failed with Couldn't send feedback (couldn't reach the service), which is why this is filed on GitHub.
Showing cached comments. Read the full discussion on GitHub ↗
3 Comments
I'm on Optimum in the NYC area, hitting Cloudflare's "EWR" site, and that the same upload fails to Cloudflare but succeeds to AWS.
Same failure here, and I have transcript data showing it depends on request size, not the network.
Setup: Claude Code desktop app 2.1.281 → 2.1.284, macOS 26 (Darwin 25.2.0), Opus 5.5. No proxy or VPN.
What I see: only
Connection dropped (ECONNRESET). There are no 429s, no 5xx and no context-limit errors. Once a session crosses a size threshold, every retry fails and the session is unusable.It's per-request size, not the connection. These are the same minutes on the same machine and network:
| Window (UTC) | Small session (~0.5 MB body) | Large session (~9 MB body, 25 images + 272k tokens) |
|---|---|---|
| 2026-09-30 20:25–20:40 | 31/31 requests OK | 0/9 OK (all retries ECONNRESET) |
| 2026-09-25 21:40–21:56 | 6/6 OK | 1/12 OK (~13 MB body, 900k tokens) |
Onset: the same large session carried 12.6 MB of images and ~870k tokens with essentially no errors (one isolated reset) from July to Sep 20. It first failed on 2026-09-23 and was unusable from 09-24.
Timing of failed attempts: retries die after a steady ~15.9 s regardless of body size (0.2 MB to 13 MB). First attempts die at ~30.5 s. Across ~90 failures, almost all fall within ±1 s of those values (3 outliers).
Ruled out locally:
tengu_byte_stream_idle_timeout_msis 180000 in the local flag cache, so it isn't the client's stream-idle watchdog.This matches the edge-side RST and SACK-gap analysis above: large request bodies get reset upstream. Because images dominate body size (~95% of bytes in my case) and are re-sent on every turn and retry, image-heavy sessions die first. Resuming a session the next day triggers it reliably.
Update from the original reporter: routing through Cloudflare WARP made this go away for me.
I installed the 1.1.1.1 app on 2026-09-23 and have kept it on in WARP mode (traffic + DNS, not DNS-only) since then. In the week since, I haven't hit a single
Connection dropped (ECONNRESET), on the same machine and ISP, with the same kind of large-context Opus (1M) sessions that were failing before.This fits what the comments above and #89608 / #74758 / #87500 describe: the problem is the specific ISP -> Cloudflare edge path mangling large request bodies, not the upload itself. With WARP the traffic reaches Cloudflare over a different path and the resets stop.
Caveats: it's a workaround, not a fix, and I haven't run a controlled A/B (WARP off on a known-bad day), so I can't rule out that something changed server-side in the same window. But for anyone hitting this, WARP is free and worth a try.