[Windows] Persistent ECONNRESET on streaming API connections due to missing SO_KEEPALIVE (~346s pattern)
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Claude Code on Windows repeatedly loses its streaming API connection with ECONNRESET after approximately 340–360 seconds of inactivity within a session. This has occurred consistently since at least May 2026 across multiple Claude Code versions (v1.6608.2.0 through v2.1.165), and persists even after configuring Windows TCP keepalive at the OS level — suggesting the application does not set SO_KEEPALIVE on its API sockets.
From %APPDATA%\Claude\logs\main.log:
[warn] [CCD CycleHealth] <session_id> api_error (success): API Error: Unable to connect to API (ECONNRESET)
[info] [CCD CycleHealth] unhealthy cycle for <session_id> (350s, hadFirstResponse=true, reason=api_error)
[error] Session <session_id> query error: Claude Code process exited with code 1073807364
From telemetry (1p_failed_events files), tengu_api_retry events:
{
"attempt": 6,
"error": "Connection error.",
"provider": "firstParty",
"attempt_duration_ms": 15019,
"delayMs": 17906
}
All 6 retries are exhausted before the session terminates.
Statistical pattern (extracted from rotated log main1.log, 30+ incidents since 2026-05-10):
hadFirstResponse=truein every single case — connection and first response always succeed; reset happens mid-session- Cycle duration at error clusters tightly at 337–355 seconds — far too consistent to be random; matches the NAT idle TCP timeout of the home router
- Longer sessions involving active tool calls do not hit the timeout (the data flow resets the NAT idle timer)
OS-level TCP keepalive is already configured:
HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
KeepAliveTime = 0xEA60 (60,000 ms = 60 s)
KeepAliveInterval = 0x2710 (10,000 ms = 10 s)
Despite this, the ~346 s ECONNRESET pattern continues unchanged. On Windows, KeepAliveTime only applies to sockets that have SO_KEEPALIVE explicitly enabled by the application (socket.setKeepAlive(true) in Node.js). The fact that the 60 s OS setting has no effect is strong evidence that the API connection socket does not have SO_KEEPALIVE set.
What Should Happen?
The streaming API connection should survive periods of inactivity (e.g., while Claude is processing a long task with no intermediate output). TCP keepalive probes should be sent at a sub-NAT-timeout interval to keep the connection alive through home routers.
Suggested fix: Enable TCP keepalive on the socket used to connect to api.anthropic.com:
// When creating the HTTPS socket / agent for the Anthropic API
agent.on('socket', (socket) => {
socket.setKeepAlive(true, 30_000); // start probes after 30 s idle
});
A 30-second initial delay would ensure probes are sent well before typical consumer router NAT timeouts (commonly 300–360 s).
Error Messages/Logs
# From %APPDATA%\Claude\logs\main.log
[warn] [CCD CycleHealth] local_b81ef33e-... api_error (success): API Error: Unable to connect to API (ECONNRESET)
[info] [CCD CycleHealth] unhealthy cycle for local_b81ef33e-... (350s, hadFirstResponse=true, reason=api_error)
[error] Session local_b81ef33e-... query error: Claude Code process exited with code 1073807364 { stack: 'Error: Claude Code process exited with code 1073807364\n at _er.getProcessExitError ...' }
# From telemetry 1p_failed_events (tengu_api_retry, base64-decoded additional_metadata)
{"subscription_type":"pro","attempt":6,"delayMs":17906.33,"error":"Connection error.","provider":"firstParty","attempt_duration_ms":15019}
{"subscription_type":"pro","attempt":6,"delayMs":16020.17,"error":"Connection error.","provider":"firstParty","attempt_duration_ms":18970}
# Unhealthy cycle durations sampled from main1.log (30+ occurrences since 2026-05-10)
# hadFirstResponse=true in all cases
346s, 346s, 344s, 349s, 350s, 352s, 353s, 347s, 344s, 346s, 347s, 350s, 337s, 343s, 355s, 344s, 346s, 350s, 352s, 341s ...
Steps to Reproduce
- Start a Claude Code session on Windows (Claude Desktop app)
- Begin a task that involves long processing time — e.g., asking Claude to analyze a large codebase or run multiple sequential tool calls
- Wait without interacting (let Claude "think" or process without user messages)
- After approximately 340–360 seconds since the last data was received on the API stream, the session terminates with ECONNRESET
- Claude Code retries 6 times (each attempt ~15–19 s) then session dies
Note: The timeout is triggered by inactivity in the TCP stream, not by any user-facing timeout. Sessions with frequent tool calls (continuous data flow) can run for hours without hitting this issue. The ~346 s threshold matches the NAT idle TCP timeout of common consumer routers (IO DATA WN-PL1167EX03 in this case, not user-configurable).
Claude Model
None
Is this a regression?
No, this never worked
Last Working Version
_No response_
Claude Code Version
2.1.165 (claude-sonnet-4-6)
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
Non-interactive/CI environment
Additional Information
- Entrypoint: claude-desktop (Claude Desktop app for Windows), not CLI
- Auth method: OAuth (
is_claude_ai_auth: true, not API key) - Node.js version: v24.3.0
- Router: IO DATA WN-PL1167EX03 — NAT TCP session timeout is not user-configurable on this consumer device
- MCP tool count: 96 tools loaded (noted in telemetry
mcpToolCount: 96) — long thinking periods increase exposure to the timeout netsh int tcp show globaldoes not expose akeepalivetimeparameter — OS keepalive must be set via registry and only takes effect ifSO_KEEPALIVEis set per-socket by the application- The issue also appears in the Anthropic SDK level — the fix should be applied wherever the streaming HTTPS connection to
api.anthropic.comis established