Remote Control WebSocket disconnects every ~25 min, permanently dies after 3rd reconnect (1006 → 1002)

Resolved 💬 5 comments Opened Mar 7, 2026 by mhhursh Closed Apr 21, 2026

Summary

Claude Code's Remote Control feature disconnects repeatedly due to server-side WebSocket closures, eventually giving up permanently. SSH and screen sharing to the same machine remain stable — only the Remote Control WebSocket is affected.

Environment

  • Machine: Mac Mini (Apple Silicon), macOS, hardwired ethernet
  • Network: 867 Mbps down, 874 Mbps up, 10ms latency (verified via networkQuality)
  • Claude Code version: Latest as of 2026-03-07
  • Power settings: sleep 0, displaysleep 0, standby 0, powernap 0, tcpkeepalive 1 — machine never sleeps
  • Uptime: 15+ hours, zero sleep/wake transitions

Behavior

The WebSocket connection to api.anthropic.com/v1/session_ingress/ws/... follows a repeatable pattern:

  1. Connects successfully
  2. Keep-alive pings sent every 5 minutes (working correctly)
  3. ~25 minutes later, server drops the connection with close code 1006 (abnormal closure — no close frame sent)
  4. Client reconnects successfully within ~1 second
  5. Steps 2–4 repeat two more times (cycle is ~25 min each)
  6. On the 3rd reconnect attempt, server responds with close code 1002 (protocol error)
  7. Client treats 1002 as permanent and stops reconnecting:

``
WebSocketTransport: Permanent close code 1002, not reconnecting
[bridge:repl] Reconnect exhausted (code=1002), falling back to poll loop
``

  1. Remote Control shows as disconnected in the UI. Only manual /remote-control toggle restores it.

Evidence from debug logs

Two independent sessions show the exact same pattern at the exact same timestamps, confirming this is server-side:

Session 1 (~/.claude/debug/07e4a19b-...txt)

00:29:39 keep_alive sent
00:29:45 [ERROR] Closed: 1006 → reconnect → Connected
00:54:47 keep_alive sent
00:54:53 [ERROR] Closed: 1006 → reconnect → Connected
01:19:54 keep_alive sent
01:20:01 [ERROR] Closed: 1006 → reconnect attempt
01:20:02 [ERROR] Closed: 1002 → Permanent close, not reconnecting

Session 2 (~/.claude/debug/4b43221f-...txt)

00:29:38 keep_alive sent
00:29:44 [ERROR] Closed: 1006 → reconnect → Connected
00:54:45 keep_alive sent
00:54:52 [ERROR] Closed: 1006 → reconnect → Connected
01:19:53 keep_alive sent
01:19:59 [ERROR] Closed: 1006 → reconnect attempt
01:20:01 [ERROR] Closed: 1002 → Permanent close, not reconnecting

Both sessions disconnect within 1 second of each other at each cycle — this is not a client or network issue.

What was ruled out

  • No system sleep eventspmset -g log shows zero sleep/wake transitions
  • No network interface changes — ethernet link stayed up, no flaps in system logs
  • No kernel or powerd disruptions — only benign hourly DarkWake probes (unrelated)
  • SSH and screen sharing remain connected indefinitely to the same machine
  • Network quality is excellent — sub-10ms latency, ~870 Mbps both directions

Expected behavior

  • The WebSocket should not be dropped every 25 minutes while keep-alives are being sent
  • If it is dropped, reconnection should not be permanently abandoned after 3 attempts — it should continue retrying with backoff since the connection does successfully re-establish each time
  • At minimum, the client should not treat a transient 1002 as permanent when the prior reconnects all succeeded

Suggested improvements

  1. Server-side: Investigate why the WebSocket gateway is closing connections every ~25 min despite active keep-alives
  2. Client-side: Don't treat 1002 as permanently fatal after successful prior reconnects — use exponential backoff and keep retrying
  3. Client-side: Surface the "fell back to poll loop" state more clearly in the UI so users know what happened

🤖 Filed with help from Claude Code

View original on GitHub ↗

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