Skip to content

[Bug][SSH]: "Connection lost before handshake" is treated as permanent, so the app stops reconnecting #25786

Closed

Description

@prateek

Environment. Desktop from main, SSH host reached through a local forwarder (the same
shape as a ProxyJump or any local proxy), link cut and restored.

Steps. Connect; cut the link so the SSH handshake fails with the ssh2 library's
"Connection lost before handshake"; restore the link; wait.

Expected. The failure is temporary and the app retries once the link is back.

Actual. The host stays in error: "Connection lost before handshake" with no retry, 150 s
after the link returned. The temporary-failure list in
src/main/ssh/ssh-reconnect-error-classification.ts:6-29 contains 'lost connection' but not
'connection lost', so src/main/ssh/ssh-connection.ts:1770-1772 classifies it as permanent.

Evidence. One occurrence in the relay-process investigation (scratchpad relay-leak/
run logs); the string is node_modules/ssh2/lib/client.js:753.

Evidence and method. From the 2026-10-05 terminal latency matrix (10 interleaved runs per network profile, Linux tc/netem on the container's own interface, real Claude Code and Codex on a stub API). Analysis and raw records: https://gist.github.com/prateek/c2b2bfc6b0079dfa01c5ac53cfc3ae46 (bash regenerate.sh reproduces every table). The harness is PR #25771; the desktop specs and a repro spec for this bug are in a follow-up PR (link to come). Related: #18957, #23595.


via Prateek's agent (claude-code)

Activity

  1. prateek commented on Oct 6, 2026

    @prateek
    ContributorAuthor

    Caveat on how this was observed: the test rig reaches the container through a local forwarder that accepts the app's connection at once and only closes it when its own connect to the container fails (macOS Local Network privacy blocks the test binary from container IPs). That turns a connect-time failure into a silent close during the SSH handshake, which is the shape that produces this error string. A direct connection would get a connect error and take the retry path. So the rig makes this easier to hit than a plain network does; the classification gap itself ('connection lost' vs 'lost connection' in ssh-reconnect-error-classification.ts) applies to any proxy or jump host that closes mid-handshake. The forwarder is being changed to refuse the connection instead (PR #25792).


    via Prateek's agent (claude-code)

  2. AmethystLiang commented on Oct 6, 2026

    @AmethystLiang
    Contributor

    Thanks for reporting. Looking into it

  3. self-assigned this
    on Oct 6, 2026
  4. OrcaWin commented on Oct 9, 2026

    @OrcaWin
    Collaborator

    Thanks for catching this. It's fixed on main by #24863: "connection lost before handshake" is now treated as a temporary network failure, so the app keeps retrying once the link comes back. If you still see a host stuck on that error on a current build, please reopen with details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions