[BUG] Desktop SSH remote: ~2s handshake timeout is unreachable at 250ms RTT — 139 session drops in one day

Status Open
Reported on v2.1.222
Maintainer reply None cached
Activity 0 comments · opened Aug 10, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code

What's Wrong?

The desktop app's SSH remote transport gives up on the SSH handshake after ~2 seconds. On a high-latency link (~250 ms RTT, Bali → Germany) the handshake reliably takes 2.5–3.5 s, so a large fraction of connection attempts fail before they can succeed. The failures then feed an auto-reconnect loop that never converges.

The 2 s ceiling is visible in the log as a tight cluster of failure durations, which is what makes this a hard-coded timeout rather than a network problem:

| duration (ms) | count |
|---|---|
| 2031 | 5 |
| 2032 | 7 |
| 2033 | 7 |
| 2034 | 3 |
| 2035–2039 | 5 |
| 2069, 2097 | 2 |

44 of 53 connection failures on 2026-08-10 were Connection lost before handshake, all in this band. A further 7 were Timed out while waiting for handshake.

The network is not the problem. Measured from the same machine at the same time:

  • TCP connect to the SSH port: 0.26–0.42 s, 10/10 samples, no loss, no outliers
  • Full SSH handshake via system ssh (ControlMaster=no): 2.83–6.79 s, median 3.4 s over 15 samples — not one sample under 2 s
  • Server side: iowait 0 % for the whole day, load 8–17 (same as days without drops), sshd rejecting nothing (0 drops, MaxStartups never reached)

The handshake cost is round-trip count, not bandwidth: KEX plus auth at 250 ms RTT cannot fit in 2 s. Any user more than ~1500 km from their remote host hits this.

Impact

On 2026-08-10 this produced 139 session-drop events in one day (50 Abandoning (transport lost, no reattach), 73 heartbeat misses, 20 Ping failed, marking connection dead), against 3–15 on each of the preceding days. Sessions were dropped mid-turn with work in flight.

The loop is self-sustaining: server.ping times out → client marks the connection dead → auto-reconnect → the reconnect needs a fresh handshake → that handshake exceeds 2 s → failure → retry. Successful reconnects took 14–35 s (median 21.5 s, max 78.7 s), during which the next heartbeat had already expired.

Steps to Reproduce

  1. Set up an SSH remote host with ~250 ms RTT from the client (e.g. client in Southeast Asia, server in the EU).
  2. Open several remote sessions in the desktop app and leave them running.
  3. Watch ~/Library/Logs/Claude/ssh.log.

Expected: connections succeed, allowing for the link's real latency.
Actual: repeated Connection lost before handshake at ~2032 ms, followed by Abandoning (transport lost, no reattach).

Suggested Fix

Make the handshake timeout adaptive rather than fixed — for example derive it from the measured TCP connect time (say 10× RTT with a floor), or expose it as a setting. The same applies to the RPC ping timeout, which has the same root cause and was reported in #49094 (closed as inactive, no fix): timeouts sized for sub-200 ms links have no accommodation for anything slower.

Environment

  • Claude desktop app: 1.26832.0
  • macOS 26.5.1 (Apple Silicon)
  • Remote: Ubuntu 24.04.4 LTS, ccd-cli 2.1.222, server binary 5db5e4a12f88487e47c2c48259b69a2d630bb3f7
  • Link: residential fibre in Bali → Contabo VPS in Germany, ~250 ms RTT, no packet loss

Related

  • #49094 — RPC ping timeout too short for Azure Bastion tunnels. Same class of bug (fixed timeout vs. high RTT), closed by the stale-issue bot without a fix.
  • #33041 — Remote Control disconnects frequently
  • #78666 — auto-reconnect exhausts after 3 attempts (~6 s), no further retry

View original on GitHub ↗