[BUG] ECONNRESET on direct ISP path: Anthropic ingress resets TLS 1.3 handshakes carrying X25519MLKEM768; classical key share or VPN is 12/12 (re-open of #74767, still on 2.1.270)

Status Open
Reported on v2.1.270
Maintainer reply None cached
Activity 8 comments · opened Sep 14, 2026

What's Wrong?

Claude Code fails with API Error: Connection dropped (ECONNRESET) in windows of minutes to hours on my ISP path (Movistar / Telefónica, Spain, home fibre and office, Wi-Fi and Ethernet). curl, the browser and claude.ai are clean at the same moment. A VPN makes it go away completely.

I isolated it to the TLS 1.3 key share: the Anthropic ingress at 160.79.104.10:443 resets handshakes whose ClientHello carries X25519MLKEM768 (about 1.7 KB, two TCP segments) on this path, and never resets a classical X25519:P-256 ClientHello (about 300 B, one segment). Claude Code's client (Bun / BoringSSL) always offers X25519MLKEM768 and has no setting to disable it, so it is the only client on the machine that fails. curl (LibreSSL, no PQ share) and Node with ecdhCurve restricted to classical never fail.

This is the same isolation as the last human comment on #74767 (another user, Argentina, Node 24+/OpenSSL 3.5), which was auto-closed for inactivity on 2026-09-04. Support ticket 215475788280207 (2026-09-04) has had no reply in 10 days. It is still reproducible today on 2.1.270.

Same interface, same minute, alternating only the key-share configuration (12 fresh TLS 1.3 POSTs to api.anthropic.com, Python 3 / OpenSSL 3.6.3):

| time | groups offered | ok | reset |
|---|---|---|---|
| 10:10:01 | X25519:P-256 | 12 | 0 |
| 10:10:05 | default incl. X25519MLKEM768 | 5 | 7 |
| 10:10:10 | X25519:P-256 | 12 | 0 |
| 10:10:14 | default incl. X25519MLKEM768 | 6 | 6 |

Path is the variable, not the client. Same PQ ClientHello, same minute (2026-09-14, Claude Code 2.1.270, Bun 1.4.3):

| path | ok | reset |
|---|---|---|
| en0 direct (Movistar), bound with IP_BOUND_IF | 5 | 7 |
| ipsec0 (CyberGhost VPN) | 12 | 0 |

Across two weeks the direct path gives 3/9, 4/8, 5/7, 4/8 in failing windows and 12/12 through the VPN every time. Control hosts with the same PQ ClientHello on the direct path: github.com 12/12, www.google.com 12/12.

A classical-TLS proxy proves the cause. A local Caddy reverse proxy with GODEBUG=tlsmlkem=0 (Go omits the ML-KEM share) forwarding to https://api.anthropic.com, with the CLI pointed at it via ANTHROPIC_BASE_URL: 12/0 on every cycle while the direct PQ probe next to it gave 4/8 and 5/7. I cannot keep that workaround because Remote Control refuses to start when ANTHROPIC_BASE_URL is not api.anthropic.com, and the desktop app overrides the variable in every session it launches.

Packet capture of a reset: TCP handshake completes, the two ClientHello segments are ACKed, the server sends one packet and then RST about 1 ms later. Capture and probe scripts available on request.

What Should Happen?

Claude Code should connect on the same network where curl, the browser and claude.ai work. Either the ingress accepts two-segment ClientHellos on this path, or Claude Code exposes a way to offer only classical key shares (the equivalent of Node's --tls-keylog-free ecdhCurve / Go's GODEBUG=tlsmlkem=0), so a paying customer does not need a permanent VPN.

Error Messages/Logs

[ERROR] API error (attempt 11/11): undefined Connection error.
[ERROR] Connection error details: code=ECONNRESET, message=The socket connection was closed unexpectedly.
[ERROR] API error x-client-request-id=8dc5ace8-1362-4c11-9306-dd5d2496a1c9

Steps to Reproduce

  1. On an affected path, run Claude Code with the VPN off: claude "what is 2+2" fails with ECONNRESET after retries.
  2. In the same minute, run 12 TLS 1.3 POSTs to api.anthropic.com:443 with OpenSSL 3.5+ default groups (includes X25519MLKEM768): some are reset by the server.
  3. Repeat with SSL_CTX_set1_groups_list("X25519:P-256"): 12/12 ok.
  4. Repeat step 2 through any VPN: 12/12 ok.

What I ruled out

MTU (1500, DF pings at 1472/1400/1200 clean), IPv6 (ISP gives none), macOS firewall, system proxies, third-party network extensions, memory pressure, sleep/wake, Wi-Fi vs Ethernet, two different networks, client versions 2.1.252 through 2.1.270.

Related

#74767 (auto-closed, same isolation in its last comment), #93031, #87424, #90764, #91970, #90964, #92227 (same symptom: only Claude Code fails, VPN or hotspot fixes it). #89608 is a different mechanism (keep-alive reuse past the 400 s edge idle timeout) and does not explain fresh-socket handshake resets.

Claude Code Version

2.1.270 (native install, Bun 1.4.3)

Platform

Claude Max subscription (OAuth, no API key)

Operating System

macOS 26 (Darwin 25.5.0), Apple Silicon

View original on GitHub ↗

4 Comments

rubenmuehlhans · 1 month ago

Same symptom here, and a VPN fixes it.

Setup: Claude Desktop (Code tab), bundled Claude Code 2.1.270, macOS 26 (Darwin 25.5.0), Claude subscription (OAuth). ISP: eins energie (local provider), Germany, home Wi-Fi (Wi-Fi 6, −45 dBm, no packet loss to router or 1.1.1.1). No system proxy; Little Snitch network extension is active.

Observations from local session transcripts (type: system, subtype: api_error):

  • 2026-09-14: 511 retries, all Connection dropped (ECONNRESET), against only 386 successful responses that day. Bursts mainly 17:20–18:50 CEST, single drops until ~21:00.
  • On most days the ECONNRESET rate is zero; on bad days it goes up to ~10–50 % of requests. Other recent bad days: 2026-09-07, 09-09, 09-13.
  • None of these are stream idle timeouts; CLAUDE_STREAM_IDLE_TIMEOUT_MS / API_TIMEOUT_MS are irrelevant (desktop already sets API_TIMEOUT_MS=900000).
  • No status page incident at those times.

Kernel log (log show, process claude): during a burst the client repeatedly opens fresh TCP connections to 160.79.104.10:443, which are closed within a few hundred milliseconds of connecting (e.g. 17:22:12 CEST, several in a row on consecutive local ports). This looks like failing handshakes on fresh sockets, not long-lived streams being cut, which matches your isolation.

Workaround: enabling a WireGuard VPN makes the errors stop immediately.

I haven't run the X25519MLKEM768 vs. X25519:P-256 probe yet; I'll post counts if I catch another failing window without the VPN.

Visible symptom in the desktop app: partially streamed output disappears and the response restarts (retry before a block completes), without an explicit error.

gdn992 · 27 days ago

Seeing the same symptom (Hungary, Magyar Telekom VDSL, same IP 160.79.104.10). I didn't dig as deep as the TLS ClientHello analysis above, but here's the isolation testing I did on my end — consistent with the same conclusion (client-side issue, not local network):

<details>
<summary>Click to expand: full isolation report</summary>

Claude Code — Persistent ECONNRESET / "Connection dropped" errors (client-side, isolated from network)

Environment

  • Claude Code version: 2.1.274
  • OS: macOS (Apple Silicon, macOS Tahoe 26.7)
  • Device: Corporate-managed (MDM) laptop
  • Network: Home broadband (VDSL, consumer ISP router), also occurs less frequently on office network
  • Install method: native (installed via curl -fsSL https://claude.ai/install.sh | bash)

Symptom

Frequent, recurring failures during normal use of the CLI:

Connection dropped (ECONNRESET) · Retrying in Xs · attempt N/10

and, in claude --debug output:

API error (attempt 1/11): undefined Connection error.
Stale connection — disabling keep-alive for retry
API error (attempt 2/11): undefined Connection error.
Stale connection — disabling keep-alive for retry
API error (attempt 3/11): undefined Connection error.
...
1P event logging: <N> events failed to export (code=ECONNRESET, socket hang up)

Errors occur in bursts lasting a few minutes, separated by periods of stability ranging from minutes to tens of minutes — consistent with other reports of this issue.

Notably, the client does detect the stale connection and attempts to disable keep-alive before retrying, but the very next attempt fails with the same "undefined Connection error" almost immediately. The stale-connection recovery logic does not appear to actually resolve the problem.

Troubleshooting already performed (all ruled out)

  1. Fully restarted the Claude Code process/session (fresh claude invocation) — no change.
  2. Checked local DNS resolution (scutil --dns) — resolves normally via the router, no anomalies, single IP for api.anthropic.com.
  3. Set IPv6 to link-local only — no consistent improvement.
  4. Disabled "Limit IP Address Tracking" (macOS Wi-Fi privacy feature) — no change.
  5. Ran a raw curl loop (for i in 1..10; do curl -s -o /dev/null -w "%{http_code}\n" https://api.anthropic.com/v1/messages; sleep 1; done), completely independent of Claude Code:
  • At one point in time: intermittent failures (roughly 1 in 3 requests returned no response / connection reset).
  • At a different point in time: 20/20 requests succeeded with no failures.
  • This shows the raw network path itself is not consistently broken — behavior varies over time.
  1. traceroute and mtr (both ICMP and TCP SYN on port 443, mtr --tcp -P 443) to the resolved IP showed 0% packet loss across every hop, ruling out a lossy network path.
  2. Verified only a single IP is returned for api.anthropic.com (no multi-IP/edge round-robin complicating the picture).
  3. Attempted testing via a VPN client — later determined to be a split-tunnel corporate VPN that did not actually route traffic to api.anthropic.com through the tunnel, so this test was inconclusive and is not used as evidence either way.
  4. Confirmed the device is under MDM management; checked profiles show -type configuration — no configuration profiles installed. Checked scutil --proxy — no proxy configured. Searched running processes for known EDR/security agents (CrowdStrike, Zscaler, Netskope, SentinelOne, Jamf Protect, Cisco Umbrella/AnyConnect, Forcepoint, etc.) — none found, only Apple's built-in XProtect.
  5. Key isolating test: While the failing Claude Code session was actively producing repeated "Connection dropped" errors, a parallel raw curl loop to the exact same endpoint, on the same machine, same network, at the same time, succeeded on every single request. This isolates the problem to the Claude Code client's connection handling, not the OS network stack or the physical network.
  6. DMZ test: Temporarily placed the affected machine in the router's DMZ (fully bypassing NAT/firewall filtering for that single host) to rule out router-side interference. The Stale connection — disabling keep-alive for retry → API error pattern continued unchanged with DMZ enabled, ruling out the home router's NAT/firewall as the cause.

Conclusion

Based on the isolation tests above (parallel curl success during Claude Code failure, no packet loss on any hop, no proxy/EDR/MDM profile involvement, and no change with router NAT/firewall fully bypassed via DMZ), the issue appears to be in Claude Code's own client-side connection handling (stale HTTP/2 connection pool detection and recovery), not in the network, ISP, router, or any local security software.

This matches the pattern described in several existing public reports of Claude Code ECONNRESET issues, where curl/other HTTP clients succeed on the same network at the same time that Claude Code's bundled client fails.

Suggested next steps for investigation

  • Review the stale-connection retry logic: the client detects a stale connection and disables keep-alive for the retry, but the retry still fails immediately with the same error — the recovery path itself may be broken rather than just the initial detection.
  • Compare behavior across the underlying HTTP runtime (Bun vs Node) since prior reports suggest the issue may be specific to the bundled Bun HTTP client's connection pooling on macOS.

</details>

tiendo1011 · 15 days ago

Additional reproduction on a different home ISP path (Viettel, Vietnam), tested 2026-09-29.

macOS 27.0 arm64, Claude Code 2.1.284; TLS probes used Node 24.6.0 / OpenSSL 3.5.2. Wi-Fi was off and the Mac connected directly to the H646EW, bypassing the ASUS: source 192.168.1.4, gateway 192.168.1.1 (en6). AiProtection is off. Both Anthropic hostnames resolve to 160.79.104.10.

TLS 1.3 results on that Ethernet path:

  • Default groups: ECONNRESET for api.anthropic.com and platform.claude.com.
  • Restricting groups to X25519:P-256: both connect successfully.
  • Default groups connect to Google and GitHub. To 160.79.104.10, they reset even with SNI example.com; classical groups with that SNI connect.

Route: 192.168.1.1 → 27.72.224.1 → 27.67.66.190 → 27.68.194.118 → 10.81.33.185 → 10.81.34.163 → 103.22.203.120 → 103.22.203.25 → 160.79.104.10.

Claude Code fails on this home connection but works on a phone hotspot. The ASUS is bypassed in this reproduction. I could not capture the reset source, so I can’t distinguish Anthropic’s ingress from an IP-aware filter on the route. Could you check handling of hybrid ClientHellos at 160.79.104.10 and advise on a supported client workaround or fix?

tiendo1011 · 15 days ago

Additional A/B results from an affected Mac on the home connection (Claude Code 2.1.284; ASUS Wi-Fi to Huawei H646EW; no HTTP(S)_PROXY environment variables):

I ran a direct TLS probe to api.anthropic.com (160.79.104.10), with no HTTP proxy and no HTTP request. On the same interface, two rounds produced:

  • Go 1.25 default TLS key shares (including X25519MLKEM768): 0/12 succeeded each round; every failure was ECONNRESET.
  • Explicit classical X25519/P-256 key shares: 12/12 succeeded each round.

Disabling the Huawei SPI firewall did not change Claude Code's failure. A temporary localhost relay using the classical key-share list allowed Claude Code to return OK over the home connection. This strongly isolates the failure to the hybrid TLS ClientHello on this path. Please provide a supported way to disable that key share in Claude Code, or fix the affected API ingress/path so the default ClientHello succeeds. I want to use the home connection without a proxy or VPN.

Showing cached comments. Read the full discussion on GitHub ↗