wavetermdev/waveterm · error
failed to create process controller: %w
Error message
failed to create process controller: %w
What it means
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.
Source
Thrown at pkg/genconn/genconn.go:69
type ShellClient interface {
MakeProcessController(cmd CommandSpec) (ShellProcessController, error)
}
type ShellProcessController interface {
Start() error
Wait() error
Kill()
// these are not required to be called, if they are not called, the impl will set to discard output
StdinPipe() (io.WriteCloser, error)
StdoutPipe() (io.Reader, error)
StderrPipe() (io.Reader, error)
}
func RunSimpleCommand(ctx context.Context, client ShellClient, spec CommandSpec) (string, string, error) {
proc, err := client.MakeProcessController(spec)
if err != nil {
return "", "", fmt.Errorf("failed to create process controller: %w", err)
}
stdout, err := proc.StdoutPipe()
if err != nil {
return "", "", fmt.Errorf("failed to get stdout pipe: %w", err)
}
stderr, err := proc.StderrPipe()
if err != nil {
return "", "", fmt.Errorf("failed to get stderr pipe: %w", err)
}
if err := proc.Start(); err != nil {
return "", "", fmt.Errorf("failed to start process: %w", err)
}
stdoutBuf := syncbuf.MakeSyncBuffer()
stderrBuf := syncbuf.MakeSyncBuffer()
var wg sync.WaitGroupView on GitHub (pinned to a4447c1563)
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.
Example fix
// before
stdout, stderr, err := genconn.RunSimpleCommand(ctx, client, spec)
if err != nil {
return err
}
// after
stdout, stderr, err := genconn.RunSimpleCommand(ctx, client, spec)
if err != nil {
if strings.Contains(err.Error(), "failed to create process controller") {
if err := conn.Reconnect(ctx); err != nil {
return fmt.Errorf("connection lost: %w", err)
}
stdout, stderr, err = genconn.RunSimpleCommand(ctx, client, spec)
}
if err != nil {
return err
}
} Defensive patterns
Strategy: retry
Validate before calling
func clientReady(client genconn.ShellClient) error {
if client == nil {
return fmt.Errorf("nil shell client")
}
_, _, err := genconn.RunSimpleCommand(context.Background(), client,
genconn.CommandSpec{Cmd: "true"})
return err
} Try / catch
stdout, stderr, err := genconn.RunSimpleCommand(ctx, client, spec)
if err != nil && strings.Contains(err.Error(), "failed to create process controller") {
if rerr := reconnect(ctx); rerr != nil {
return fmt.Errorf("conn unusable: %w", rerr)
}
stdout, stderr, err = genconn.RunSimpleCommand(ctx, client, spec)
}
if err != nil {
return err
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- cannot parse connection name: %w
- getting ssh connection status: %w
- connecting connection: %w
- cannot start shellproc: %w
- not connected: %s
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/531bdfe601a6b666.
Report an issue: GitHub.