[BUG] Windows: Remote-control CLI process becomes zombie with CloseWait TCP socket after server-side idle timeout

Resolved 💬 3 comments Opened Mar 30, 2026 by garyhaith Closed Apr 3, 2026

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?

When a Claude Code remote-control session (launched from the Claude Desktop app) goes idle for ~20+ minutes on Windows, the server-side TTL expires and closes the connection. However, the CLI process (claude.exe) does not detect the dead connection and continues running indefinitely as a zombie process.

Observed behavior:

  • The CLI process remained alive for 20+ hours after the connection died
  • TCP connection to Anthropic API (2607:6bc0::10:443) stuck in CloseWait state — the server closed its end, but the client never acknowledged
  • Process consumed 1.07 GB private memory while completely idle (only 2 min 18s CPU time over 20 hours)
  • 3 MCP server ports remained bound serving nothing
  • The session appeared active in the desktop app but was completely unresponsive
  • No automatic recovery or graceful exit occurred

Diagnostic evidence (PowerShell):

Get-NetTCPConnection -OwningProcess <PID> | Select LocalAddress, LocalPort, RemoteAddress, RemotePort, State

LocalAddress                            LocalPort RemoteAddress RemotePort  State
::                                          50151 ::                     0  Bound
::                                          50149 ::                     0  Bound
::                                          50147 ::                     0  Bound
2605:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx     50147 2607:6bc0::10        443  CloseWait

Related: This is the Windows-side manifestation of #32982 (server-side TTL ignores keepalives). While #32982 focuses on the server-side root cause, this issue highlights a separate client-side bug: the CLI process should detect the dead connection (via CloseWait state or read timeout) and either reconnect or exit gracefully, rather than sitting as a zombie consuming 1GB+ RAM indefinitely.

What Should Happen?

When the server-side TTL expires and the API connection is closed, the CLI process should:

  1. Detect the dead connection within a reasonable timeout (e.g., 30-60 seconds) via TCP read errors or CloseWait detection
  2. Attempt to reconnect to the remote-control bridge automatically
  3. If reconnection fails, exit gracefully and release all resources (memory, bound ports, MCP server sockets)
  4. Surface the disconnection to the desktop app UI so the user knows the session is dead, rather than showing it as still active

The CLI process should never remain running indefinitely as a zombie consuming 1GB+ of RAM with no active connections.

Error Messages/Logs

Steps to Reproduce

  1. Open Claude Desktop app (v1.1.9493) on Windows 11
  2. Start a remote-control session (a claude.exe --output-format stream-json process is spawned)
  3. Use the session briefly, then leave it idle for 20+ minutes
  4. Attempt to send a message via the mobile app or desktop — it fails silently or shows "Failed to send message"
  5. On the Windows machine, check the CLI process:
  • tasklist | findstr claude — zombie CLI process still running
  • Get-NetTCPConnection -OwningProcess <PID> — shows CloseWait connection to Anthropic API
  • Process memory continues to be held (1GB+) indefinitely
  1. The only fix is manually killing the process: taskkill /PID <PID> /F

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.87

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

PowerShell

Additional Information

Environment:

  • Claude Desktop: v1.1.9493 (Windows Store)
  • Claude Code CLI: v2.1.87
  • OS: Windows 11 Pro 10.0.26200
  • Hardware: Lenovo Yoga 9i
  • Plugins loaded: Slack, Telegram

Suggested client-side fixes:

  1. Add a TCP-level read timeout or periodic health check on the API WebSocket connection
  2. Detect CloseWait state and trigger reconnection or graceful shutdown
  3. Implement an idle watchdog that exits the CLI if no API activity for N minutes and reconnection fails
  4. Surface connection state to the desktop app so it can show "Disconnected" instead of appearing active

Workaround: Periodically run a scheduled task to detect and kill zombie sessions:

Get-NetTCPConnection -State CloseWait |
  Where-Object { (Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).Path -match 'claude-code' } |
  ForEach-Object { Stop-Process -Id $_.OwningProcess -Force }

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗