{"record":{"id":"531bdfe601a6b666","repo":"wavetermdev/waveterm","slug":"failed-to-create-process-controller-w","errorCode":null,"errorMessage":"failed to create process controller: %w","messagePattern":"failed to create process controller: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/genconn/genconn.go","lineNumber":69,"sourceCode":"type ShellClient interface {\n\tMakeProcessController(cmd CommandSpec) (ShellProcessController, error)\n}\n\ntype ShellProcessController interface {\n\tStart() error\n\tWait() error\n\tKill()\n\n\t// these are not required to be called, if they are not called, the impl will set to discard output\n\tStdinPipe() (io.WriteCloser, error)\n\tStdoutPipe() (io.Reader, error)\n\tStderrPipe() (io.Reader, error)\n}\n\nfunc RunSimpleCommand(ctx context.Context, client ShellClient, spec CommandSpec) (string, string, error) {\n\tproc, err := client.MakeProcessController(spec)\n\tif err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"failed to create process controller: %w\", err)\n\t}\n\n\tstdout, err := proc.StdoutPipe()\n\tif err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"failed to get stdout pipe: %w\", err)\n\t}\n\tstderr, err := proc.StderrPipe()\n\tif err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"failed to get stderr pipe: %w\", err)\n\t}\n\n\tif err := proc.Start(); err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"failed to start process: %w\", err)\n\t}\n\n\tstdoutBuf := syncbuf.MakeSyncBuffer()\n\tstderrBuf := syncbuf.MakeSyncBuffer()\n\tvar wg sync.WaitGroup","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/genconn/genconn.go#L51-L87","documentation":"RunSimpleCommand executes a shell command through a ShellClient abstraction (SSH or WSL). The client's MakeProcessController builds the platform-specific process object (e.g. exec.Cmd or an SSH session wrapper) from the CommandSpec; this error wraps any failure in that construction step, before the process is started or any pipes are created. It indicates the client could not even prepare the process, usually because the underlying connection or session is unusable.","triggerScenarios":"client.MakeProcessController(spec) returns an error: the SSH session cannot be created on the existing connection, the remote/WSL shell client is nil or disconnected, or the CommandSpec is rejected by the client implementation. Called via GetClientPlatform and other RunSimpleCommand callers.","commonSituations":"SSH connection dropped or timed out before running a remote command; trying to run a command on a WSL distro that is not installed; calling RunSimpleCommand with a client whose connection was closed upstream.","solutions":["Verify the underlying connection is alive before calling (ping or run a trivial command via the same client).","Inspect the wrapped error: 'session: request failed' style errors mean the SSH connection is stale — reconnect and retry.","If WSL, confirm the distro exists: wsl -l -v.","Ensure the ShellClient passed in is non-nil and was constructed from a valid, connected conn.","Add retry-once-after-reconnect logic around RunSimpleCommand for transient connection drops."],"exampleFix":"// before\nstdout, stderr, err := genconn.RunSimpleCommand(ctx, client, spec)\nif err != nil {\n    return err\n}\n// after\nstdout, stderr, err := genconn.RunSimpleCommand(ctx, client, spec)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to create process controller\") {\n        if err := conn.Reconnect(ctx); err != nil {\n            return fmt.Errorf(\"connection lost: %w\", err)\n        }\n        stdout, stderr, err = genconn.RunSimpleCommand(ctx, client, spec)\n    }\n    if err != nil {\n        return err\n    }\n}","handlingStrategy":"retry","validationCode":"func clientReady(client genconn.ShellClient) error {\n    if client == nil {\n        return fmt.Errorf(\"nil shell client\")\n    }\n    _, _, err := genconn.RunSimpleCommand(context.Background(), client,\n        genconn.CommandSpec{Cmd: \"true\"})\n    return err\n}","typeGuard":null,"tryCatchPattern":"stdout, stderr, err := genconn.RunSimpleCommand(ctx, client, spec)\nif err != nil && strings.Contains(err.Error(), \"failed to create process controller\") {\n    if rerr := reconnect(ctx); rerr != nil {\n        return fmt.Errorf(\"conn unusable: %w\", rerr)\n    }\n    stdout, stderr, err = genconn.RunSimpleCommand(ctx, client, spec)\n}\nif err != nil {\n    return err\n}","preventionTips":["Validate the connection with a cheap command before batch runs","Keep SSH/WSL connections warm with keepalives","Never pass a client built from a closed conn","For WSL, verify the distro is installed and running first","Reconnect-and-retry once on controller-creation failures"],"tags":["process","ssh","wsl","connection"],"backgroundTag":"process-spawn-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}