{"record":{"id":"46bee07b0f526976","repo":"wavetermdev/waveterm","slug":"wsl-connection-s-not-connected-cannot-start-shel","errorCode":null,"errorMessage":"wsl connection %s not connected, cannot start shellproc","messagePattern":"wsl connection (.+?) not connected, cannot start shellproc","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/blockcontroller/shellcontroller.go","lineNumber":345,"sourceCode":"\tWshEnabled bool\n\tShellPath  string\n\tShellOpts  []string\n\tShellType  string\n\tHomeDir    string\n}\n\nfunc (bc *ShellController) getConnUnion(logCtx context.Context, remoteName string, blockMeta waveobj.MetaMapType) (ConnUnion, error) {\n\trtn := ConnUnion{ConnName: remoteName}\n\twshEnabled := !blockMeta.GetBool(waveobj.MetaKey_CmdNoWsh, false)\n\tif strings.HasPrefix(remoteName, \"wsl://\") {\n\t\twslName := strings.TrimPrefix(remoteName, \"wsl://\")\n\t\twslConn := wslconn.GetWslConn(wslName)\n\t\tif wslConn == nil {\n\t\t\treturn ConnUnion{}, fmt.Errorf(\"wsl connection not found: %s\", remoteName)\n\t\t}\n\t\tconnStatus := wslConn.DeriveConnStatus()\n\t\tif connStatus.Status != conncontroller.Status_Connected {\n\t\t\treturn ConnUnion{}, fmt.Errorf(\"wsl connection %s not connected, cannot start shellproc\", remoteName)\n\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 {","sourceCodeStart":327,"sourceCodeEnd":363,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/blockcontroller/shellcontroller.go#L327-L363","documentation":"Thrown by getConnUnion when the named WSL connection exists (GetWslConn returned it) but its DerivedConnStatus is not Status_Connected. Wave refuses to start a shell process in a WSL distro whose connection is not fully established, since commands could not be reliably executed there.","triggerScenarios":"Calling DoRunShellCommand / setupAndStartShellProcess for a block whose remoteName maps to a WSL distro while wslconn.GetWslConn(wslName) returns a connection whose DeriveConnStatus().Status is Connecting, Error, or Disconnected.","commonSituations":"WSL distro still booting or the wsh connection handshake still in progress; the distro was registered but the underlying wsl.exe process exited; network/auth issues interrupted the WSL bridge; user reopened a terminal block right after app start before the connection reconnected.","solutions":["Wait for the WSL connection to reach Status_Connected (watch DeriveConnStatus) and retry the shell command","Reconnect the WSL connection explicitly (trigger the connection controller's connect flow) before starting the shell","Check that the WSL distro itself is healthy: `wsl -l -v` shows Running and `wsl -d <distro> echo ok` works","Restart Wave Terminal so the WSL connection is re-established from scratch"],"exampleFix":"// before: immediately starting shell after resolving conn\nshellProc, err := bc.setupAndStartShellProcess(logCtx, rc, blockMeta)\n\n// after: verify connection status first\nconnStatus := wslconn.GetWslConn(wslName).DeriveConnStatus()\nif connStatus.Status != conncontroller.Status_Connected {\n    // reconnect or surface 'connecting...' UI before retry\n    return fmt.Errorf(\"wsl %s still connecting, retry later\", wslName)\n}\nshellProc, err := bc.setupAndStartShellProcess(logCtx, rc, blockMeta)","handlingStrategy":"validation","validationCode":"wslConn := wslconn.GetWslConn(wslName)\nif wslConn == nil || wslConn.DeriveConnStatus().Status != conncontroller.Status_Connected {\n    return fmt.Errorf(\"wsl %s not ready; wait for connected state\", wslName)\n}","typeGuard":"func isWslConnected(c *wslconn.WslConn) 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    // schedule retry after connection-state event signals Connected\n}","preventionTips":["Gate shell start on a connection-state change event instead of calling immediately","Show a 'connecting' placeholder in the UI until DeriveConnStatus reports Connected","Use `wsl -l -v` health checks when diagnosing persistent non-connected states"],"tags":["wsl","connection-state","shell-process"],"backgroundTag":"wsl-connection-not-connected","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}