{"record":{"id":"b7774c3b9069575b","repo":"wavetermdev/waveterm","slug":"failed-to-create-ssh-session-w","errorCode":null,"errorMessage":"failed to create SSH session: %w","messagePattern":"failed to create SSH session: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/genconn/ssh-impl.go","lineNumber":48,"sourceCode":"type SSHProcessController struct {\n\tclient      *ssh.Client\n\tsession     *ssh.Session\n\tlock        *sync.Mutex\n\tonce        *sync.Once\n\tstdinPiped  bool\n\tstdoutPiped bool\n\tstderrPiped bool\n\twaitErr     error\n\tstarted     bool\n\tcmdSpec     CommandSpec\n}\n\n// MakeSSHCmdClient creates a new instance of SSHCmdClient\nfunc MakeSSHCmdClient(client *ssh.Client, cmdSpec CommandSpec) (*SSHProcessController, error) {\n\tlog.Printf(\"SSH-NEWSESSION (cmdclient)\\n\")\n\tsession, err := client.NewSession()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create SSH session: %w\", err)\n\t}\n\treturn &SSHProcessController{\n\t\tclient:  client,\n\t\tlock:    &sync.Mutex{},\n\t\tonce:    &sync.Once{},\n\t\tcmdSpec: cmdSpec,\n\t\tsession: session,\n\t}, nil\n}\n\n// Start begins execution of the command\nfunc (s *SSHProcessController) Start() error {\n\ts.lock.Lock()\n\tdefer s.lock.Unlock()\n\n\tif s.started {\n\t\treturn fmt.Errorf(\"command already started\")\n\t}","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/genconn/ssh-impl.go#L30-L66","documentation":"MakeSSHCmdClient calls client.NewSession() on an established golang.org/x/crypto/ssh connection to open a channel for running a command. If the underlying SSH connection cannot open a new session channel (connection dropped, closed, or refused by the server), the error is wrapped as 'failed to create SSH session'. This happens before any command is built or started.","triggerScenarios":"Calling MakeSSHCmdClient (directly or via SSHShellClient.MakeProcessController, used by MakeProcessController and CpWshToRemote) when the *ssh.Client's underlying connection has been closed/reset, the server rejects the session channel (MaxSessions reached), or the connection was never fully established.","commonSituations":"Remote host restarted or network dropped mid-connection; SSH server's MaxSessions limit hit (default 10); connection idle-timeouted by firewall/server (ClientAliveInterval); trying to reuse a client after a previous command's connection was torn down; server's sshd configured to disallow exec sessions (allowtcpforwarding/no-exec chroot).","solutions":["Check/verify the SSH connection is still alive (e.g. client.SendRequest keepalive) before creating the session; if dead, reconnect and rebuild the *ssh.Client.","Retry the operation with a fresh connection — transient network drops are the most common cause.","Raise MaxSessions on the remote sshd_config if many concurrent sessions are needed.","Check server logs (auth.log/sshd -d) to confirm whether the server is rejecting channels."],"exampleFix":"// before\nctrl, err := genconn.MakeSSHCmdClient(client, cmdSpec)\nif err != nil { return err }\n// after\nif _, err := client.SendRequest(\"keepalive@openssh.com\", true, nil); err != nil {\n    client, err = reconnectSSH(cfg) // rebuild dead connection\n    if err != nil { return err }\n}\nctrl, err := genconn.MakeSSHCmdClient(client, cmdSpec)\nif err != nil { return err }","handlingStrategy":"retry","validationCode":"func sshAlive(client *ssh.Client) bool {\n    _, _, err := client.SendRequest(\"keepalive@openssh.com\", true, nil)\n    return err == nil\n}\nif !sshAlive(client) { client = mustReconnect() }","typeGuard":null,"tryCatchPattern":"ctrl, err := genconn.MakeSSHCmdClient(client, cmdSpec)\nif err != nil {\n    log.Printf(\"ssh session open failed: %v; reconnecting\", err)\n    client = reconnectSSH(cfg)\n    ctrl, err = genconn.MakeSSHCmdClient(client, cmdSpec)\n    if err != nil { return fmt.Errorf(\"ssh session unavailable: %w\", err) }\n}","preventionTips":["Send SSH keepalive requests (SendRequest keepalive@openssh.com) to detect dead connections early.","Reconnect and rebuild the *ssh.Client on any session-creation failure instead of retrying on the stale client.","Cap concurrent sessions per connection below sshd's MaxSessions (default 10).","Monitor connection lifetime and proactively reconnect before server idle timeouts."],"tags":["ssh","network","session"],"backgroundTag":"ssh-session-open-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}