Persistent ECONNRESET Errors on macOS Network Connections
Bug Description
I keep getting the following errors, and it's causing connection errors and it's disconnecting tasks within Claude. This only happens on my Mac OS; it doesn't happen on my Windows server (which is on the same network) nor does it happen on my Linux server (which is on an OCI network). I've read online that this is an issue with Mac OS. I have been troubleshooting all day for over 10 hours, and I can't figure out what's going on. I believe this is a Claude issue, not a user issue. If it is a user issue, please guide me in regards to how to resolve this issue because I am stumped. I have been working on this for over 12 hours now, and that made zero progress.
These are the errors that I see: n, pass verbose: true in the second argument to fetch()) (ECONNRESET)
⎿ API Error (Connection error.) · Retrying in 32 seconds… (attempt 7/10)
⎿ Error (The socket connection was closed unexpectedly. For more information, pass verbose: true in the second argument to fetch()) (ECONNRESET)
⎿ API Error (Connection error.) · Retrying in 37 seconds… (attempt 8/10)
⎿ Error (The socket connection was closed unexpectedly. For more information, pass verbose: true in the second argument to fetch()) (ECONNRESET)
⎿ API Error (Connection error.) · Retrying in 33 seconds… (attempt 9/10)
⎿ Error (The socket connection was closed unexpectedly. For more information, pass verbose: true in the second argument to fetch()) (ECONNRESET)
⎿ API Error (Connection error.) · Retrying in 40 seconds… (attempt 10/10)
⎿ Error (The socket connection was closed unexpectedly. For more information, pass verbose: true in the second argument to fetch()) (ECONNRESET)
⎿ API Error: Connection error.
Environment Info
- Platform: darwin
- Terminal: Apple_Terminal
- Version: 1.0.77
- Feedback ID: 64d3964f-f289-4803-a28c-1fd74ede068e
Errors
[{"error":"Error\n at <anonymous> (unknown)\n at onData (node:child_process:153:110)\n at emit (node:events:95:22)\n at addChunk (internal:streams/readable:265:47)\n at readableAddChunkPushByteMode (internal:streams/readable:243:18)\n at handleNumberResult (internal:streams/native-readable:69:18)\n at <anonymous> (internal:streams/native-readable:43:68)\n at processTicksAndRejections (unknown:7:39)","timestamp":"2025-08-13T09:22:33.750Z"},{"error":"Error: Connection error.\n at new eW (unknown:1:28)\n at new qY (/$bunfs/root/claude:788:1853)\n at new BM (/$bunfs/root/claude:788:2749)\n at makeRequest (/$bunfs/root/claude:805:4449)\n at processTicksAndRejections (native:7:39)","timestamp":"2025-08-13T09:32:49.094Z"}]
48 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
I'm not sure if this is a duplicate because this is only occurring on macOS and some other people are seeing it on Windows. I think this requires further investigation.
I'm getting connectivity issues across all apps (including Anthropic's Claude desktop app) and web requests (Chrome).
The issues go away when I shut down from Claude Code instances (running in a terminal inside Cursor)
I'm on an Apple M2 Pro
macOS
version: 15.6
I'm having the same @yasserlens' error. Any thought?
@MarceloCajueiro my issue is now resolved - it had nothing to do with the Claude app it seems. Turns out this problem I had was due to using a VPN (TunnelBear) which seemed to have had issues. Uninstalling and deleting it helped (although was a challenge - uninstalling it didn't remove all pieces of the software that interfered with the network so I had to do some stuff manually). All done with the help of ChatGPT/Claude :)
Thanks for the light @yasserlens! Here is the diagnostic and probably solution.
🔍 Additional Root Cause: VPN Residue Causing ECONNRESET on macOS
I experienced similar ECONNRESET issues on macOS after uninstalling a VPN client. Through investigation with Claude Code, we discovered leftover VPN network configurations were interfering with socket connections.
Diagnostic Findings
System: macOS 15.0.0 (Darwin 25.0.0)
Symptoms:
``
``default → fe80::%utun0
default → fe80::%utun1
default → fe80::%utun2
default → fe80::%utun3
default → fe80::%utun4
default → fe80::%utun5
How This Causes ECONNRESET
The multiple competing IPv6 routes cause routing conflicts where:
This explains why it's macOS-specific and intermittent (depends on which route the OS chooses).
Diagnostic Commands
If you see 4+ utun interfaces and multiple IPv6 default routes, VPN residue is likely interfering.
✅ Solution That Worked
Disable IPv6 on Wi-Fi:
Results:
To re-enable:
sudo networksetup -setv6automatic Wi-FiWhy This Happens
After VPN uninstallation, macOS system services (
nesessionmanager,rapportd) don't properly clean up tunnel interfaces. Research from Apple Developer Forums (2024-2025) confirms:ifconfig destroyfails)Alternative Solutions
If you need IPv6:
``
bash
``# Check utun count
netstat -rn | grep "default.*utun" | wc -l
# If >3, reboot
Feature Request
Could Claude Code detect VPN residue during connection errors and suggest network cleanup? Something like:
References
---
This solution might help others experiencing ECONNRESET on macOS after using VPN software. The key indicator is multiple utun interfaces with competing routes.
This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.
This turned out to also be a network configuration error for me, but specifically with my MTU setting (and possibly eero secure).
When looking at my primary wireless interface (
en0), I had an mtu of 1500:Setting my MTU to
1492(I had tried just 1400 originally) made everything work fine again.One thing that pointed me _away_ from it just being a CC issue was that I also couldn't load https://docs.bsky.app or https://superuser.com with Chrome or Vivaldi (but Safari worked fine). They're all behind a CloudFlare CDN so I don't know if they're implementing some TLS 1.3 thing in a specific way or what.
OK after tons of troubleshooting, it turns out the presence of Tailscale on my Mac, which I forgot I had installed and which was periodically launching, was my problem. This was causing intermittent failures, only on certain network stacks, that was driving me insane. Wanted to post this here to help others who might have this issue. Check your network and VPN setup!!
Update: More specifically, Tailscale (I suspect) set my TCP MSS (max segment size) to 512. Insane. Should be 1460, and presumably many apps expect that value. As Claude reports:
You can temporarily fix this on your Mac with
sudo sysctl -w net.inet.tcp.mssdflt=1460but that does not persist after reboot. I found it very difficult to remove residual Tailscale daemons, they stayed even after it was completely removed from System Settings. But maybe by adjusting that setting you can use Claude Code to track it down, which is what I did!We are experiencing the same error, and none of the above tips have worked. Please help!
The issue with me is the Tidal Exclusive Mode. I don't know much about technical, so here is what I found :
Use Tidal without Exclusive Mode solve this with me.
FWIW: This happened to me and after some debugging, it was Lulu/little snitch that was blocking
claude😄Facing same issue. Without using a VPN I get this error constantly. Began happening randomly one day last week
Can't submit /feedback as it fails with or without VPN
Claude desktop app and web works with and without VPN, issue just affects claude code
# ECONNRESET on macOS Despite All Network Connectivity Verified — Claude Code Internal Connection Handling Bug
Environment
| Component | Detail |
|:-:|:-:|
| OS | macOS (Apple Silicon / arm64) |
| Node | v22.17.0 (via nvm) |
| Claude Code | 2.1.30 (tested both native Bun install and npm Node install — identical failure) |
| Auth | OAuth, Max subscription |
| Working comparison | Same account/credentials work fine on Linux (Ubuntu, Claude Code 2.1.29) on the same network |
Summary
Claude Code 2.1.30 fails with ECONNRESET on every API call on macOS. Extensive troubleshooting has confirmed the issue is internal to Claude Code's connection handling, not the network, runtime, SDK, or auth.
What Works (all from the same Mac)
⠀What Fails
⠀Verified Not the Cause
⠀Debug Log Evidence
2026-02-03T21:56:26.297Z [DEBUG] [API:request] Creating client, ANTHROPIC_CUSTOM_HEADERS present: false, has Authorization header: false
2026-02-03T21:56:26.297Z [DEBUG] [API:auth] OAuth token check starting
2026-02-03T21:56:26.297Z [DEBUG] [API:auth] OAuth token check complete
...
2026-02-03T21:56:27.374Z [ERROR] Error: Error: Connection error.
at makeRequest (/$bunfs/root/claude:361:4548)
at processTicksAndRejections (native:7:39)
Network-Level Observations
The connection does establish to 160.79.104.10:443 (confirmed via lsof) but then immediately resets. The lsof output shows the TCP socket transitions from ESTABLISHED to CLOSED state shortly after connecting:
node 11075 patrick 22u IPv4 0x2dc13daa605e3e7 0t0 TCP 192.168.x.x:50972->160.79.104.10:443 (CLOSED)
Notably, marketplace refresh succeeds within the same process:
2026-02-03T21:56:30.997Z [DEBUG] Successfully refreshed marketplace: claude-plugins-official
This suggests only specific API request paths are affected.
Telemetry Also Fails with the Same Error
[ERROR] Error: Error: 1P event logging: 26 events failed to export
(code=ECONNRESET, The socket connection was closed unexpectedly.
For more information, pass
verbose: truein the second argument to fetch())Suspected Cause
Something in Claude Code's internal HTTP client configuration or request construction is triggering a connection reset that does not occur when using the same SDK, same runtime, same credentials, and same endpoints outside of Claude Code. The fact that the marketplace refresh succeeds while API calls and telemetry fail within the same process suggests the issue may be specific to how certain requests are constructed or routed internally.
Steps to Reproduce
I was able to resolve this through a system reboot of all things. No clarity on why this worked.
Thank you, this fixed it for me!
Update: Found a deeper root cause beyond VPN/sysctl — Node.js HTTP/1.1 connection exhaustion
I commented here before about VPN residue and utun interfaces. That was real but turned out to be only part of the problem. After months of dealing with this intermittently, I finally spent a full day doing systematic testing and found the actual root cause — and it's something that affects every Node.js app on macOS, not just Claude Code.
The real problem
Node.js
fetch(via undici) uses HTTP/1.1 by default, which opens one TCP connection per request. CDNs like Cloudflare limit concurrent TCP connections per IP to roughly 50-150. When any Node.js process on your machine exceeds that threshold, the server starts refusing connections with ECONNRESET/ECONNREFUSED.Here's the critical part that explains why your browser stops working too: Cloudflare uses shared IPs. When your Node.js app floods
160.79.104.10:443(Anthropic's Cloudflare-fronted API) with hundreds of HTTP/1.1 connections, Cloudflare can temporarily block your IP for all domains behind that CDN — GitHub, NPM, Discord, and thousands of other sites suddenly become unreachable from your browser.curland browsers don't have this problem because they use HTTP/2 by default, which multiplexes all requests over a single TCP connection.Proof
I ran a controlled test battery against external APIs:
| Method | 200 concurrent requests | 300 concurrent |
|---|---|---|
|
fetch(HTTP/1.1) | 4 ok, 196 fail | worse ||
https.get(HTTP/1.1) | 3 ok, 197 fail | worse ||
http2(native) | 200 ok, 0 fail | 300 ok, 0 fail ||
fetch+allowH2| 200 ok, 0 fail | 300 ok, 0 fail || localhost (any method) | 1000 ok, 0 fail | — |
Localhost never fails because there's no per-IP connection limit. The problem is exclusively with remote servers.
Why this is particularly bad on macOS
macOS has some TCP defaults that make this worse:
tcp.mssdflt= 512 (dial-up era value — several people in this thread found this, including @brigleb with Tailscale)tcp.blackhole= 1 (silently drops packets instead of sending RST)tcp.msl= 2000 (TIME_WAIT only 4 seconds — connections get recycled too aggressively)These sysctl values compound the HTTP/1.1 connection flood problem. VPNs like Tailscale, TunnelBear, and Cloudflare WARP can also set
mssdfltto 512, which fragments packets and makes HTTP/2 streaming fail even when the protocol negotiation works.How I'm solving it (3 layers)
Layer 1: Enable HTTP/2 globally for all Node.js processes
This makes every Node.js process (Next.js, Inngest, scripts, tests) negotiate HTTP/2 automatically. If the server only supports HTTP/1.1, it falls back gracefully. Zero code changes required in any project.
Important limitation: this does NOT affect Claude Code itself (it's a Bun binary, not Node.js) or the AWS SDK (
@aws-sdk/client-s3), which uses its own HTTP client.Layer 2: Fix macOS TCP sysctl defaults
For persistence, create
/Library/LaunchDaemons/custom.sysctl.tuning.plistwith those values.| Parameter | macOS default | Fixed | Why |
|---|---|---|---|
|
tcp.mssdflt| 512 | 1440 | 512 is dial-up era; 1440 is correct for MTU 1492 ||
tcp.blackhole| 1 | 0 | Was silently dropping packets instead of RST ||
tcp.msl| 2000 | 15000 | TIME_WAIT was 4s, way too aggressive ||
tcp.delayed_ack| 3 | 0 | Immediate ACK, less latency |Layer 3: For apps using AWS SDK / S3Client (Cloudflare R2, S3, etc.)
The AWS SDK v3 uses
node:httpsinternally with no keepAlive by default — everyPutObject,GetObject, etc. opens a new TCP connection. If your endpoint is Cloudflare R2 (*.r2.cloudflarestorage.com), this can trigger the same CDN-wide IP block:What does NOT work
| Approach | Result |
|---|---|
|
dns.setDefaultResultOrder("ipv4first")| Makes it worse (1/100 success) — disables Happy Eyeballs RFC 8305 || Increasing
http.globalAgent.maxSockets| Doesn't help — more sockets = more refusals from server || Semaphore/queue to limit concurrency | Palliative — complex and fragile, HTTP/2 solves it at the root |
| sysctl tuning alone | Doesn't solve it — helps marginally but root cause is HTTP/1.1 |
How this relates to other comments in this thread
tcp.mssdflt=512from Tailscale — that's Layer 2 above. But even after fixing MSS, HTTP/1.1 connection floods can still trigger CDN blocks.mssdflt=512AND create routing conflicts. Removing the VPN fixes both, but you can also fix MSS directly without removing the VPN.Diagnostic one-liner
For the Claude Code team
Claude Code itself (Bun binary) likely already uses HTTP/2 via Bun's fetch. But the subprocesses it spawns (MCP servers, tool calls, etc.) that use Node.js would be affected by HTTP/1.1 connection exhaustion. If Claude Code is making many concurrent API calls (parallel tool use, streaming + telemetry + marketplace refresh simultaneously), the HTTP/1.1 connections from those Node.js subprocesses could be triggering CDN rate limiting that then also affects the main Bun process.
Worth considering: should Claude Code set
NODE_OPTIONSwithallowH2for spawned Node.js subprocesses by default?Mac M1. For me claude worked on mobile hotspot but not on my home wifi. I struggle with that few weeks. I had to remove all network configurations by these commands:
then reboot
Now it works. Maybe this will help someone.
Still experiencing this on macOS (Darwin 25.3.0) with Claude Code using Opus 4.6.
Consistent with the HTTP/2 stale connection pooling theory from #23744.
After 8 days after my post (https://github.com/anthropics/claude-code/issues/5674#issuecomment-3881326808) I can say properly that worked for me forcing to use HTTP/2.
I have the same problem using Claude Cowork on windows.
This really helped me, man. Thanks a lot. IOU
This might be useful for debugging for some scenarios
https://gist.github.com/pacificsky/5a4e85aa98a9c88110dd534c819390f9
I had exactly the same problem on a brand new freshly installed MacBook Pro, so no VPN cruft, etc etc.
claude -p "<prompt>" worked fine, but interactive mode gave me consistent ECONNRESET errors.
Dropping the MTU on my Mac from 1500 down to 1450 fixed it for me. Setting it back to anything higher instantly gave me ECONNRESETs again, switch it back down to 1450 fixed. This was 100% reproducible.
You may have to tweak the numbers depending on your network setup, perhaps down as far as 1436.
Fun fact ...
My project is using Symfony Proxy in order to run my app.
Claude decided to create a startup script, and created the json file
.claude/settings.json:It launched the preview but the Symfony proxy was not running.
So all the Claude session requests, not only the project one, where going through this proxy that was not running because claude named the proxy environment variable the same as it seems to be using internally.
Starting the Symfony Proxy made it work.
I deleted the settings files and just run it manually. Working fine now.
Same problem here, with more tan 60 times on a morning
this is also happening for me inside a linux container running inside proxmox
API Error: The socket connection was closed unexpectedly. For more information, pass
verbose: truein the second argument to fetch()Me as well, never used to get this, am getting it several times a day now.
This was related to a bug if IPv6 not resolving in my machine
dude, you are absolute genius!
@MarceloCajueiro Thanks for your deep insight, but it seems not work for me.
Error
Whatever
claudeorollama launch claude, it will prompt 'Unable to connect to API (ECONNREFUSED)' even for '/init'.Verify: node.js
fetch[concurrent-fetch.js]
Then the testing result says that
fetchworks fine, not like what you said "4 ok, 196 fail".Try Layer 1
Then
claudeorollama launch claudestill same error.Try Layer 2
Then
claudeorollama launch claudestill same error.What a pity.
Same. Did all the recommended steps – Claude does few responses and then gets stuck. Gets unstuck after ide reboot but then gets stuck again. Pretty annoying problem.
jfyi: I have vpn on (can't test without it for my own reasons)
Any solution for this? I'm getting the same issue on an M4, and I never uninstalled any VPN service. The same doesn’t seem to happen on Linux or Windows on the same network. I need to send the same prompt multiple times just to get it to work.
Same issue happens in my mac m4 and wsl. I never uninstall any VPN service.
When I start some a little long and complex work, it will be stuck and get the error.
i just started getting this issue today out of nowhere.
This issue is highly visible in version
2.1.143Claude
2.1.126still works fineI started using claude desktop app and never seen that problem ever since. Only happens in cursor for me
It's happen to me to after electric drop. I try many way but didn't resolve.
last shot I try to connect with Warp by Cloudflare...It's fix!!!
Root cause identified — Bun does not set
SO_KEEPALIVEon TCP socketsPosting here as this is the most active thread. We did a deep binary-level investigation on Linux (Arch/Manjaro) and found the root cause. Full report in #60133.
What's happening
The claude binary is a standalone Bun 1.3.14 executable (confirmed via
strings). Bun'sfetch()does not setSO_KEEPALIVEon its TCP sockets. During agentic sessions, the HTTP/2 connection sits idle while tools execute locally. Without keepalive probes, the connection is silently dropped by the router, ISP, or Anthropic's server — and Bun only discovers this when it tries to reuse the connection for the next API call.Confirmed via
ss -tnop state established '( dport = :443 )':Additionally, all application-level keepalives are explicitly disabled via GrowthBook feature flags in
~/.claude.json:Why Cloudflare Warp fixes it on macOS
Warp routes traffic through a VPN tunnel that enforces its own keepalive at the tunnel layer — effectively compensating for the missing
SO_KEEPALIVEin Bun. That's the same reason it "just works" through Warp.Workaround (Linux/macOS)
Add to
~/.zshrcor~/.bashrc:For a more reliable OS-level fix, build an LD_PRELOAD shim that forces
SO_KEEPALIVEon every TCP socket:Also lower the TCP keepalive probe interval:
Verified: After applying these fixes, all claude sockets show
timer:(keepalive,Xs,0)and two consecutive 90-second idle windows survive without error.Suggested fix for Anthropic
Set
SO_KEEPALIVEon the API socket — this is a one-liner and would fix the majority of reports across all platforms:Full analysis, evidence table, and binary findings: #60133
Brunos3d this is the way!
Same
ECONNRESET, but in our case the root cause was a network-layer Path-MTU black hole — not keepalive. Sharing because the fix is completely different, and the keepalive workarounds above wouldn't have helped us. (Also, heads-up for macOS readers: theLD_PRELOADshim andsysctl net.ipv4.*snippets are Linux-only — they're no-ops on macOS, where the signed/hardenedclaudebinary also ignoresDYLD_INSERT_LIBRARIES.)The tell: it wasn't only Claude Code. Chrome also failed with
ERR_CONNECTION_RESETon specific sites (Shopify-hosted stores), while Safari andcurlloaded them fine on the same network. A Claude/Bun bug can't explain Chrome breaking too — so we packet-captured it.What
tcpdumpshowed (every connection attempt, fully deterministic):That
sack {1449:1828}together withack 1is the smoking gun: the far end received the small segment but never the full-size 1500-byte one. The path silently drops 1500-byte packets and no ICMP "fragmentation needed" comes back, so PMTUD never engages → the handshake stalls and the connection is reset.Why this maps onto the reports in this thread:
ClientHellois small and fits in a sub-1500 packet.claude(Bun → BoringSSL) fail → theirClientHellois large (>1448 B) and requires a full 1500-byte segment, which is exactly what gets dropped.Fix (macOS, persistent):
After this, Claude Code stopped throwing
ECONNRESETand the sites loaded in Chrome — with no tunnel at all.30-second triage to tell the two failure modes apart:
curl https://api.anthropic.com/+ Safari are fine, but Chrome / Claude / Cursor reset on big-ClientHello sites → it's MTU/MSS → lower your MTU.SO_KEEPALIVEclass @brunos3d described.So there seem to be (at least) two distinct buckets getting merged here: (1) idle-connection drops (the keepalive story) and (2) large-ClientHello packets dying in a PMTU black hole / clamped MSS (ours, @dacort, @brigleb).
socket.setKeepAlive(true, …)would address bucket 1 but not bucket 2.Suggestion for the team: on
ECONNRESET, printing a hint like "if Chrome also fails on some sites but Safari/curl don't, try lowering your MTU (networksetup -setMTU …)" would have saved us a long debugging session.Honestly... I'm not sure who else's has tried this.. I reset my computer. That was it. The econnrest disappeared. The instances were old.. they had been massive sessions with a lot of context and left open for weeks. I always save my sessions this way, before creating handoff prompts. Resetting my entire computer, often I leave it in sleep, or if I have an automated task, it runs silently all night. Nothing anyone suggested here worked.. until I just ended all instances and reset my computer
I've been having this in "longer-lived" sessions where "longer-lived" is something like 1h+, regardless of context size. Stopping and resuming the session doesn't work, occasionally I can get it to succeed in writing a handoff doc for a new session to continue. So it's not just "week long massive sessions", as I restart my CC frequently. Not having similar issues in other browsers
/feedback doesn't work either in the sessions, so you can't even report the bug within the session! Same ECONNRESET.
Hopefully #60133 is the real issue, but damn this has been very frequent as of this week for me, it's hard to get the large work CC is useful for done.
Seems tons of similar issues since last year already:
https://github.com/anthropics/claude-code/issues/66758
https://github.com/anthropics/claude-code/issues/56017
https://github.com/anthropics/claude-code/issues/28557
https://github.com/anthropics/claude-code/issues/66090
https://github.com/anthropics/claude-code/issues/64453
https://github.com/anthropics/claude-code/issues/60441
https://github.com/anthropics/claude-code/issues/65028
https://github.com/anthropics/claude-code/issues/62045
https://github.com/anthropics/claude-code/issues/62263
https://github.com/anthropics/claude-code/issues/56059
https://github.com/anthropics/claude-code/issues/62327
https://github.com/anthropics/claude-code/issues/66127
https://github.com/anthropics/claude-code/issues/41242
https://github.com/anthropics/claude-code/issues/62971
https://github.com/anthropics/claude-code/issues/57222
https://github.com/anthropics/claude-code/issues/51164
https://github.com/anthropics/claude-code/issues/63559
I've just run into this issue today, and made progress with Fable 5, here's what we've found:
ECONNRESET on large payloads — root cause: IPv6 PMTUD black hole (postmortem)
Environment: macOS (Apple Silicon), Claude Code CLI + VS Code extension
anthropic.claude-code2.1.170, home network (Polish ISP, IPv6 prefix2a02:...), Ethernet via Dell Universal Dock D6000 (en7), no VPN.TL;DR: Persistent
ECONNRESETerrors affecting large requests only (/compact, large document reviews via subagents) were caused by a Path MTU Discovery black hole on the ISP's IPv6 path, not by Claude Code or the local TCP stack. Small requests succeeded; any request with a large upload silently stalled mid-transfer and eventually reset. Fix: disable IPv6 on the active network interface. A separate, unrelated issue — Opus retry loops that also surfaced asECONNRESET— was server-side load shedding during the June 8–10 incident window (confirmed via TCP state: server-initiated FIN after a clean 746 KB upload) and required no local action. Section 6 has a one-command discriminator table for telling the two apart.---
Symptoms
ECONNRESETerrors in VS Code extension tabs, "all the time" — but intermittent in terminal sessions./compacton a long-running (4.5h) session failed repeatedly:``
``⎿ Error: Error during compaction: API Error: Unable to connect to API (ECONNRESET)
One attempt took ~15 minutes to fail, stuck at 95% for the last ~10 minutes. Reproducible across models (failed identically on Sonnet) and across fresh processes.
Key distinguishing pattern
This is the signature that separates a PMTUD black hole from generic connectivity problems, server outages, or connection-pool exhaustion. If everything fails, it's not this. If only big payloads fail, check the items below.
---
What to check, how, and what to expect
1. Which protocol and interface your traffic is actually using
What we found (the smoking gun):
What to read from it:
| Observation | Meaning |
|---|---|
|
tcp6to2607:6bc0::10| Traffic is on IPv6 — IPv4-targeted fixes (sysctlnet.inet.tcp.mssdflt, netstat greps for160.79.x) don't apply || Interface
en7(dock), noten0(Wi-Fi) | MTU fixes applied to Wi-Fi were applied to the wrong interface || ~857 KB out vs ~13 KB in, counters frozen, dupes/retransmits | Large upload stalled mid-flight — classic PMTUD black hole: oversized segments dropped, ICMPv6 Packet Too Big never arrives, TCP retransmits into the void forever |
Pitfall we hit: the connection census
netstat -an | grep "160.79.10"came back nearly empty and looked "clean" — because it only matched IPv4. Always check both stacks:2. The mechanism (why large payloads specifically)
IPv6 routers never fragment. If a TCP segment exceeds any hop's MTU, that hop must drop it and send ICMPv6 Packet Too Big back so the sender shrinks its segments. If a middlebox filters those ICMPv6 messages (common on DS-Lite / tunneled IPv6 deployments), the sender never learns — full-size segments vanish silently, retransmits vanish too, the connection freezes, and after several minutes one side gives up →
ECONNRESET./compact(ships the entire transcript in one POST) and large file reads → guaranteed full-size segments → guaranteed stall.3. The fix
Identify the network service for the active interface and disable IPv6 on it:
This setting is stored in the network service configuration and persists across reboots — no LaunchDaemon needed. Revert later with
-setv6automatic.Result: the identical subagent task that had hung for 7+ minutes with a frozen counter completed normally immediately after the switch (visible token streaming, multi-tool-use review finished).
tcp4connections to160.79.xtook over.4. Optional: keep IPv6 by finding the true path MTU
Walk the size to the cliff, set the interface MTU to
cliff + 48vianetworksetup -setMTU. If moderate sizes black-hole with-D, the ISP path is eating ICMPv6 PTB (an RFC 4890 violation worth reporting to them); leave v6 off until fixed.5. What did NOT fix it (tried first, ruled out)
| Attempted fix | Outcome | Why it couldn't work |
|---|---|---|
|
NODE_OPTIONSundiciallowH2preload (from #5674) | No effect | Claude Code is a Bun binary — the Node preload never loads in the main process; also GUI-launched VS Code doesn't inherit shell env ||
sysctl net.inet.tcp.mssdflt=1440etc. | No effect on this bug | Tunes the IPv4 stack; traffic was on IPv6 (net.inet6.tcp6.mssdfltis the v6 knob). Alsosysctl -wis runtime-only — persists only via a LaunchDaemon plist || MTU 1492 on Wi-Fi | Seemed to help, didn't | Traffic was on
en7(dock), noten0||
pkill+ fresh session /--resume| Recovered the session, not the bug | Fresh process, same broken v6 path || Switching models (Opus → Sonnet) | No effect on the resets | Network-layer problem, model-agnostic |
6. The unrelated second issue: Opus-side ECONNRESET (server load shedding)
Important caveat for anyone reading this issue: not every ECONNRESET is a network problem. After the network fix, the same review task succeeded under Sonnet but failed under Opus 4.7 (1M) — first cycling
Retrying in 0s · attempt 5/10(fast overload-class rejections), later escalating toUnable to connect to API (ECONNRESET) · Retrying in 11s · attempt 10/10. Same machine, same path, same payload; only the model differed. A network fault can never be model-dependent.A nettop sample taken during the Opus failure proved the path was healthy and the close came from the server:
tcp4to160.79.104.10— the v6 fix held.LastAck— meaning the remote side sent FIN first. The server received the full payload and closed the connection instead of answering. That server-initiated close surfaces to the client asECONNRESET.This matched the elevated-error incidents on Opus 4.6/4.7/4.8 logged on status.claude.com around June 8–9 (Fable 5 launch window). No local action exists; use Sonnet or retry later.
One-command discriminator (
nettop -p <claude_pid> -L 2, compare the two samples):| Signal | PMTUD black hole (local/ISP path) | Server-side load shed |
|---|---|---|
| Byte counters across samples | frozen (no forward progress) | n/a — connection already closed |
|
rx_dupe/re-tx| high (we saw 27 dupes) | zero || TCP state |
Establishedbut wedged |LastAck/CloseWait(remote FIN) || Model-dependent | no — hits all models equally | yes — one model fails, another works |
| Error appearance | silent multi-minute freeze, late reset | explicit retry attempts with backoff |
7. Why it "suddenly started"
The PMTUD black hole was a latent condition on the ISP's v6 path. The likely trigger (~June 9–10): client traffic to
api.anthropic.comshifted to IPv6 — plausibly via Happy Eyeballs preferring a changed endpoint around the Fable release — moving bulk uploads onto the broken path for the first time. Cannot be proven after the fact; ISP-side routing changes are an equally valid trigger.---
Suggestion for the Claude Code team
The client retried up to 11 attempts through a black-holed connection with a frozen spinner and surfaced only a generic
ECONNRESET— this cost roughly a working day of local-stack debugging. Two cheap improvements:tcp6 via en7vstcp4 via en0) — that single line in the error output would have shortcut this entire investigation.ECONNRESETstring. The client has enough socket-level information to say "server closed the connection after receiving the request" vs. "connection stalled mid-upload" — these point to opposite ends of the wire and completely different remediations.ECONNRESET follow-up — June 11: two distinct findings (IPv6 leak via second interface + server-side drops of large requests on Sonnet 4.6)
Environment: macOS (Apple Silicon), Claude Code CLI, home network (Polish ISP), Ethernet via Dell sUniversal Dock D6000 (
en7), Wi-Fi (en0) up simultaneously. Follow-up to the June 9–10 postmortem (IPv6 PMTUD black hole, fixed by disabling IPv6 on the dock interface).TL;DR: Two separate findings today.
ifconfig | grep -c "inet6.*2a02"→ 0.---
Finding 1: the IPv6 leak (multi-homed machine trap)
Symptom
A single ECONNRESET on Sonnet 4.6 (~14:17 CET) on a machine where the v6 black-hole fix had been applied and verified the previous day. Intermittent rather than reproducible — characteristically different from the constant failures of June 9–10.
Diagnosis
The routing table showed the leak:
Wi-Fi was up alongside the dock with IPv6 enabled, advertising a v6 default route. Any dual-stack connection attempt (Happy Eyeballs) could pick v6 and land on the same broken PMTUD path. The intermittency follows: only connections that happened to choose v6 failed — frequency proportional to traffic, not deterministic.
Fix and verification
Lesson
---
Finding 2: server-side drops of large requests (Sonnet 4.6, no status-page incident)
Symptom
After the leak was closed (transport verifiably clean), an active session kept failing/retrying. Token counter advanced to 719 and froze.
Evidence —
nettop -p <pid> -L 2during the failure window (~15:22 CET)Process totals: ~10.1 MB out / ~314 KB in. Connection table (abridged; all
tcp4onen7, all0re-tx /0dupe / 1 ms RTT):Interpretation:
Closing/LastAck= remote-initiated teardown) without an HTTP response — a proper 4xx/5xx would surface as an API error, not ECONNRESET. The client retried the identical request ~16 times; cumulative upload ≈ 16 × 680 KB ≈ 11 MB.Confirming the stall — spaced sampling
nettop -L 2samples ~300 ms apart — too short to judge a slow stream. Use spaced samples:Result: port 59006 frozen at 547,476 out / 7,401 in across all three samples (20 s) — zero bytes moved process-wide. Upload complete, server silent, connection wedged. Verdict: abandoned.
Why the payload was ~680 KB per turn
The session had previously read two design documents (~1,400 lines) plus subagent results into context. Claude Code re-sends accumulated context on every turn, so the session's own history became a ~680 KB per-message toll. On a healthy edge this is invisible; on a degraded edge, context size converts directly into failure probability — each turn is another large-request lottery ticket.
Mitigation
/compacta struggling large session — compaction is itself one of the largest requests the client makes; it has worse odds than the failing turns.Status-page correlation: none
No incident was logged for Sonnet 4.6 in the failure window (June 11, ~14:00–15:30 CET). The most recent logged incident was Haiku 4.5 on June 10. This failure mode — ~6% success rate for large requests with clean transport — was apparently below Anthropic's alerting threshold, which is itself a useful data point for the report.
---
Updated discriminator table (supersedes the June 10 version)
One command —
nettop -p <claude_pid> -L 3 -s 10— separates three ECONNRESET origins:| Signal | PMTUD black hole (ISP path) | Server load shed / overload | Server drops large requests (today) |
|---|---|---|---|
| Protocol/route | tcp6, or v6 default route present | tcp4, clean | tcp4, clean |
|
re-tx/rx_dupe| high (retransmitting into void) | zero | zero || Byte counters | frozen mid-upload | n/a (closed fast) | full upload out, ~10 KB in, then frozen/closed |
| TCP states |
Established, wedged |LastAck/CloseWait| manyClosing/LastAck, one ~identical large upload each || Repetition pattern | every large request, deterministic | bursty, model-dependent | same request rejected serially, rare partial success |
| Model-dependent | no | yes | partially (whichever pool's edge is degraded) |
| Status page | n/a (local) | usually has an incident | may have none |
| Fix | disable v6 / fix path MTU on all interfaces | wait / switch model | abandon session, fresh small context |
---
Additional suggestion for the Claude Code team (beyond the June 10 list)
I think the solution is easier than we thought.
On macOS, we have the private relay always on. For some reason, it stops Claude Code. So I’ve stopped it for one day an Claude started to work straight away
Two forensic captures at the exact moment of
attempt 10/10ECONNRESET — transport verifiably clean, failure is session/payload-dependent (supports the "server drops large requests" bucket)Environment: macOS (Apple Silicon, Darwin 25.4.0), Claude Code 2.1.201, Max plan, Wi-Fi 802.11ax (SNR 54 dB, 2.1 Gbps PHY rate), no VPN, no global IPv6 addresses (all traffic tcp4).
I set up a LaunchAgent that samples every claude process's connections every 20s (
netstat+nettopper PID) and fires a deep diagnostic bundle (spaced nettop, gateway ping, 1500B don't-fragment MTU probe, fresh TLS handshake timing, DNS, status page) the moment an API error entry lands in a session transcript. That gives measurements from the exact second of failure, not after-the-fact.Ruled out on this machine before capturing (following the buckets earlier in this thread):
sudo sysctl -w net.inet.tcp.always_keepalive=1 net.inet.tcp.keepidle=60000(the macOS-native equivalent of the Linux LD_PRELOAD shim posted above — no shim needed on macOS). Verified working: idle connections now survive long local tool execution. The failures below happened anyway, so keepalive is not the remaining cause on this machine.Capture 1 (11:55 local) and capture 2 (12:01 local), both during a live
Unable to connect to API (ECONNRESET) · attempt 10/10:| Signal | Capture 1 | Capture 2 |
|---|---|---|
| Gateway RTT (local hop) | 2.75–3.02 ms, 0% loss | 2.60–3.62 ms, 0% loss |
| api.anthropic.com ICMP | avg 19 ms, 0% loss | avg 18 ms, 0% loss |
| Fresh TLS handshake to api.anthropic.com | 68 ms total (3/3 succeeded, 63–128 ms) | 83 ms total |
| 1500B DF MTU probe | pass, 0% loss | pass, 0% loss |
| status.claude.com | All Systems Operational | All Systems Operational |
Meanwhile, in the same seconds:
This matches @mmisztal1980's "server drops large requests" discriminator exactly: tcp4, clean transport, zero retransmit growth at failure time, full upload out, closed without an HTTP response, same request rejected serially, no status-page incident.
Repeating the earlier asks, which this data supports:
Happy to share the full incident logs (sampler + diagnostics) if useful. Filed via
/feedbackas well.Update: filed via
/feedbackfrom the affected session — Feedback ID:42bef73e-e462-4574-90a3-699ce52b2a77(the transcript attached there is the failing 19.4 MB session). Notably, the/feedbacksubmission itself went through on the first attempt from that same session — consistent with small requests passing while large ones get dropped.Update 2 (same day, ~5h later): two more captures with the identical signature — but on a different session (13.7 MB transcript this time): gateway 2.8–3.5 ms / 0% loss, api.anthropic.com ICMP normal, fresh TLS fine, status page green, while that session's requests died with ECONNRESET. Live observation during one failure: ~95 KB request body uploaded, then both byte counters frozen (upload complete, no response) until reset. So this is not one pathological session — any large-transcript session reproduces it, and the failing body doesn't need to be huge (~95 KB–1 MB observed). Four captures, two sessions, one signature: server-side/edge drops selecting on request size, invisible on the status page.
This is not a solution. Claude should work even with Private Relay enabled, since it is an OS default setting.