[BUG] Connection closed mid-response at ~1% of requests — quantified over 130k local transcripts (Opus 5 / 2.1.220)

Status Open
Reported on v2.1.220
Maintainer reply None cached
Activity 0 comments · opened Aug 3, 2026

"Connection closed mid-response" at ~1% of requests — quantified from 130k local transcripts

Summary

Since 2026-07-29 I hit API Error: Connection closed mid-response at roughly 1% of all
requests
(~30 occurrences/day). I parsed my full local transcript history
(~/.claude/projects/**/*.jsonl) to get a hard denominator: 130,204 API responses,
203 occurrences, 0.16% lifetime — but 1.04% since 2026-07-29.

Local network, terminal, memory and PMTU were tested and ruled out (details below).
Related open issues lack a denominator; this report provides one.

Related: #69336, #69415, #69517, #70217, #70411, #72722. Filing separately rather than
commenting because the contribution here is measurement methodology and a denominator
rather than another occurrence report — happy to have it merged into whichever thread is
canonical. A /bug feedback ID was submitted from the same machine and can be linked on
request.

Environment

  • Claude Code 2.1.220 (native install, autoUpdates: false)
  • macOS Darwin 25.4.0, Apple M5 Pro, 48 GB RAM
  • Model Opus 5 (1M context), effortLevel: xhigh, plan Claude Max
  • Home Wi-Fi, no proxy, no VPN, no TLS-inspection agent (scutil --proxy empty,

no active system extensions)

  • Reproduced in two different terminals: Orca and Warp (fresh session, first prompt)

Impact, by day

| Day | Requests | Errors | Rate |
|---|---:|---:|---:|
| 2026-07-29 | 170 | 0 | 0.00% |
| 2026-07-30 | 2,589 | 24 | 0.93% |
| 2026-07-31 | 4,335 | 48 | 1.11% |
| 2026-08-01 | 586 | 3 | 0.51% |
| 2026-08-02 | 790 | 13 | 1.65% |
| 2026-08-03 | 3,159 | 33 | 1.04% |

By model (same machine, same network, same client, all with [1m] + xhigh)

| Model | Requests | Errors | Rate |
|---|---:|---:|---:|
| claude-opus-4-8 | 57,242 | 8 | 0.01% |
| claude-fable-5 | 10,210 | 1 | 0.01% |
| claude-sonnet-5 | 29,893 | 36 | 0.12% |
| claude-haiku-4-5-20251001 | 21,279 | 37 | 0.17% |
| claude-opus-5 | 11,580 | 121 | 1.04% |

By client version

| Version | Requests | Errors | Rate |
|---|---:|---:|---:|
| 2.1.204 | 3,979 | 0 | 0.00% |
| 2.1.208 | 3,437 | 0 | 0.00% |
| 2.1.209 | 3,556 | 0 | 0.00% |
| 2.1.212 | 7,048 | 0 | 0.00% |
| 2.1.216 | 5,783 | 0 | 0.00% |
| 2.1.217 | 8,616 | 0 | 0.00% |
| 2.1.207 | 20,885 | 2 | 0.01% |
| 2.1.215 | 10,669 | 5 | 0.05% |
| 2.1.211 | 9,339 | 20 | 0.21% |
| 2.1.206 | 7,420 | 21 | 0.28% |
| 2.1.220 | 11,583 | 121 | 1.04% |

Important caveat: model and client version are confounded

I cannot separate them from my own data. claude-opus-5 and Claude Code 2.1.220 both
entered my usage on 2026-07-29, and there is no overlap:

  • 2.1.220 ran essentially only opus-5 (3 sonnet requests total)
  • opus-5 never ran on an older client

So the 1.04% could be attributable to opus-5 serving, to a regression in 2.1.220, or to the
interaction. Anthropic-side telemetry can separate these; I cannot.

Notable: 2.1.217 recorded 8,616 requests across three models with zero occurrences.

Ruled out locally (all measured, not assumed)

| Hypothesis | Test | Result |
|---|---|---|
| Packet loss / latency | 15 pings to api.anthropic.com | 0.0% loss, 26 ms avg |
| Download path | 36 × 25 MB over HTTPS | zero drops, ~27 MB/s |
| Upload path (large POST bodies) | 8 MB POST | 0.49 s, 17 MB/s |
| Connection concurrency | 12 simultaneous long streams | zero drops |
| Agent concurrency | sessions active within ±60 s of each error | median 2 at error vs 6 baseline — errors happen at lower concurrency |
| Memory pressure | 48 GB, aggregate RSS | no pressure |
| Wi-Fi instability | log show roam/deauth events, last 6 h | 0 events, while ~10 errors occurred |
| Terminal emulator | reproduced in Orca and Warp | not terminal-specific |
| Context size | context at time of error | 24,806 → 942,882 tokens; 74/198 occurred under 50k |

Two real but non-causal local findings: path MTU to the API is 1480 while the interface
is 1500 (handled by MSS clamping — 8 MB uploads pass cleanly), and the LAN is double-NATed.

Observation on retry semantics

Per the error reference, a drop before any block
completes is retried silently, while a drop after a completed text block or tool call is
not retried and surfaces this notice.

That likely explains why heavy xhigh users see this far more than others: high-effort turns
complete many blocks (my last occurrence: 1 file read, 2 directory listings, 3 shell commands,
26 s of thinking, then the drop), so nearly every drop lands in the non-retried path. The
underlying drop rate may be similar for everyone; the visible rate is not. Any fix that only
tunes retry counts will not help this class of user.

Duration before the cut (n=196)

Bimodal, which argues against a single fixed middlebox timeout:
0–10 s: 68 · 10–30 s: 25 · 30–60 s: 13 · 60–300 s: 20 · 300–600 s: 12 · >600 s: 58

How to reproduce these numbers

Occurrences counted as transcript entries containing Connection closed mid-response with
isApiErrorMessage: true (or message.model == "<synthetic>"). Denominator = entries with
type == "assistant", a real model id, and a usage object. Model/version attributed from the
last real assistant message preceding each occurrence in the same session file.

Ask

  1. Can server-side telemetry separate opus-5 serving from a 2.1.220 client regression?

My data cannot.

  1. Is the elevated rate on opus-5 visible for other high-effort / 1M-context users?
  2. Feedback IDs and the parsing script are available on request.

View original on GitHub ↗