wavetermdev/waveterm · error
failed to start remote command: %w
Error message
failed to start remote command: %w
What it means
Returned when the SSH session fails to launch the remote command, e.g. because the session is closed, the remote shell cannot be spawned, or the command request is rejected by the remote host. The underlying error is wrapped with %w so callers can inspect it via errors.Unwrap.
Source
Thrown at pkg/remote/connutil.go:140
}
blocklogger.Infof(ctx, "[conndebug] copying %q to remote server %q\n", wshLocalPath, wavebase.RemoteFullWshBinPath)
genCmd, err := genconn.MakeSSHCmdClient(client, genconn.CommandSpec{
Cmd: installCmd.String(),
})
if err != nil {
return fmt.Errorf("failed to create remote command: %w", err)
}
stdin, err := genCmd.StdinPipe()
if err != nil {
return fmt.Errorf("failed to get stdin pipe: %w", err)
}
defer stdin.Close()
stderrBuf, err := genconn.MakeStderrSyncBuffer(genCmd)
if err != nil {
return fmt.Errorf("failed to get stderr pipe: %w", err)
}
if err := genCmd.Start(); err != nil {
return fmt.Errorf("failed to start remote command: %w", err)
}
copyDone := make(chan error, 1)
go func() {
defer close(copyDone)
defer stdin.Close()
if _, err := io.Copy(stdin, input); err != nil && err != io.EOF {
copyDone <- fmt.Errorf("failed to copy data: %w", err)
} else {
copyDone <- nil
}
}()
procErr := genconn.ProcessContextWait(ctx, genCmd)
if procErr != nil {
return fmt.Errorf("remote command failed: %w (stderr: %s)", procErr, stderrBuf.String())
}
copyErr := <-copyDone
if copyErr != nil {
return fmt.Errorf("failed to copy data: %w (stderr: %s)", copyErr, stderrBuf.String())View on GitHub (pinned to a4447c1563)
Solutions
- Reconnect the SSH session and retry the install/update
- Verify the remote shell and wsh destination path are valid and writable
- Check remote host health (disk space, process limits)
- Ensure client and remote wsh versions are compatible
Example fix
// before
err := CpWshToRemote(ctx, conn, input, "/bad/path/wsh")
// after
dest := filepath.Join("/usr/local/bin", "wsh") // validate dest exists & writable
err := CpWshToRemote(ctx, conn, input, dest) Defensive patterns
Strategy: retry
Validate before calling
if conn == nil || conn.IsClosed() {
return fmt.Errorf("remote connection not available")
}
if dest == "" { return fmt.Errorf("empty destination path") } Type guard
func connReady(c *remote.Conn) bool { return c != nil && !c.IsClosed() } Try / catch
err := CpWshToRemote(ctx, conn, input, dest)
if err != nil && strings.Contains(err.Error(), "failed to start remote command") {
time.Sleep(time.Second); conn = reconnect(ctx)
err = CpWshToRemote(ctx, conn, input, dest)
} Prevention
- Verify remote shell path in config
- Ensure destination dir exists and is writable
- Confirm disk space on remote before large installs
When it happens
Trigger: UpdateWsh/InstallWsh invoking CpWshToRemote when the SSH session cannot start the remote process — dead connection, remote shell unavailable, or invalid command construction.
Common situations: Remote host unreachable mid-session; remote shell path misconfigured (bad wshconfig shell); remote disk full or permissions preventing process spawn; wsh binary path invalid on remote.
Related errors
- remote command failed: %w (stderr: %s)
- procinfo: process not found
- failed to start durable shell: %w
- failed to run app: %w
- failed to create process controller: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/7e50a1320264aaa7.
Report an issue: GitHub.