{"record":{"id":"cd1a883ca50be8b5","repo":"wavetermdev/waveterm","slug":"ssh-connection-s-not-connected-cannot-start-shel","errorCode":null,"errorMessage":"ssh connection %s not connected, cannot start shellproc","messagePattern":"ssh connection (.+?) not connected, cannot start shellproc","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/blockcontroller/shellcontroller.go","lineNumber":364,"sourceCode":"\t\t}\n\t\trtn.ConnType = ConnType_Wsl\n\t\trtn.WslConn = wslConn\n\t\trtn.WshEnabled = wshEnabled && wslConn.WshEnabled.Load()\n\t} else if conncontroller.IsLocalConnName(remoteName) {\n\t\trtn.ConnType = ConnType_Local\n\t\trtn.WshEnabled = wshEnabled\n\t} else {\n\t\topts, err := remote.ParseOpts(remoteName)\n\t\tif err != nil {\n\t\t\treturn ConnUnion{}, fmt.Errorf(\"invalid ssh remote name (%s): %w\", remoteName, err)\n\t\t}\n\t\tconn := conncontroller.MaybeGetConn(opts)\n\t\tif conn == nil {\n\t\t\treturn ConnUnion{}, fmt.Errorf(\"ssh connection not found: %s\", remoteName)\n\t\t}\n\t\tconnStatus := conn.DeriveConnStatus()\n\t\tif connStatus.Status != conncontroller.Status_Connected {\n\t\t\treturn ConnUnion{}, fmt.Errorf(\"ssh connection %s not connected, cannot start shellproc\", remoteName)\n\t\t}\n\t\trtn.ConnType = ConnType_Ssh\n\t\trtn.SshConn = conn\n\t\trtn.WshEnabled = wshEnabled && conn.WshEnabled.Load()\n\t}\n\terr := rtn.getRemoteInfoAndShellType(blockMeta)\n\tif err != nil {\n\t\treturn ConnUnion{}, err\n\t}\n\treturn rtn, nil\n}\n\nfunc (bc *ShellController) setupAndStartShellProcess(logCtx context.Context, rc *RunShellOpts, blockMeta waveobj.MetaMapType) (*shellexec.ShellProc, error) {\n\t// create a circular blockfile for the output\n\tctx, cancelFn := context.WithTimeout(context.Background(), 2*time.Second)\n\tdefer cancelFn()\n\tfsErr := filestore.WFS.MakeFile(ctx, bc.BlockId, wavebase.BlockFile_Term, nil, wshrpc.FileOpts{MaxSize: DefaultTermMaxFileSize, Circular: true})\n\tif fsErr != nil && fsErr != fs.ErrExist {","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/blockcontroller/shellcontroller.go#L346-L382","documentation":"Thrown when an SSH connection object exists for the remote but DeriveConnStatus().Status is not Status_Connected — the connection is connecting, disconnecting, in error, or idle. Wave will not start a shell process over a non-established SSH connection.","triggerScenarios":"DoRunShellCommand raced with an in-progress SSH connect, or the SSH connection transitioned to error/disconnected (network drop, host unreachable, auth timeout) right before shell startup.","commonSituations":"Laptop waking from sleep with a dead TCP session; VPN dropped; host rebooted; user clicks into a terminal block while the remote is still handshaking; flaky Wi-Fi causes DeriveConnStatus to report reconnecting.","solutions":["Retry after the connection status becomes Status_Connected (poll DeriveConnStatus or listen for connection state events)","Force a reconnect of the SSH remote (close and re-open the connection) then retry","Check network reachability of the host (ping/ssh from a plain terminal) and VPN status","If auth is the problem, fix keys/agent/passphrase so the connection can reach Connected state"],"exampleFix":"// before: unconditional retry loop hammering a down connection\nfor {\n    runShellCommand(blockId, remoteName)\n}\n\n// after: only retry when status is connected\nif conn.DeriveConnStatus().Status == conncontroller.Status_Connected {\n    runShellCommand(blockId, remoteName)\n}","handlingStrategy":"retry","validationCode":"conn := conncontroller.MaybeGetConn(opts)\nif conn != nil && conn.DeriveConnStatus().Status != conncontroller.Status_Connected {\n    return fmt.Errorf(\"ssh %s not ready (status=%s); retry on connected\", remoteName, conn.DeriveConnStatus().Status)\n}","typeGuard":"func sshReady(c conncontroller.Conn) bool {\n    return c != nil && c.DeriveConnStatus().Status == conncontroller.Status_Connected\n}","tryCatchPattern":"proc, err := bc.setupAndStartShellProcess(logCtx, rc, blockMeta)\nif err != nil && strings.Contains(err.Error(), \"not connected, cannot start shellproc\") {\n    // exponential backoff retry while connection reconnects\n}","preventionTips":["Listen for connection state transitions and only run shells when Connected","Handle sleep/resume and VPN changes by forcing a reconnect on wake","Surface connection status in the block header so users don't start shells mid-handshake"],"tags":["ssh","connection-state","network"],"backgroundTag":"ssh-connection-not-connected","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}