wavetermdev/waveterm · error
failed to create remote command: %w
Error message
failed to create remote command: %w
What it means
CpWshToRemote creates an SSH exec session via genconn.MakeSSHCmdClient to run the rendered install command on the remote host. This error is wrapped when creating that remote command client fails. It indicates the SSH layer could not set up the exec request, so nothing was streamed to the remote host.
Source
Thrown at pkg/remote/connutil.go:128
if err != nil {
return fmt.Errorf("cannot open local file %s: %w", wshLocalPath, err)
}
defer input.Close()
installWords := map[string]string{
"installDir": filepath.ToSlash(filepath.Dir(wavebase.RemoteFullWshBinPath)),
"tempPath": wavebase.RemoteFullWshBinPath + ".temp",
"installPath": wavebase.RemoteFullWshBinPath,
}
var installCmd bytes.Buffer
if err := installTemplate.Execute(&installCmd, installWords); err != nil {
return fmt.Errorf("failed to prepare install command: %w", err)
}
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 {View on GitHub (pinned to a4447c1563)
Solutions
- Verify the SSH connection is still alive (reconnect if idle) and retry InstallWsh/UpdateWsh.
- Check remote sshd config for MaxSessions limits or ForceCommand restrictions blocking exec channels.
- Ensure the genconn client passed to CpWshToRemote is the live client for the target connection, not a stale one.
- Look at the wrapped error (%w) for the underlying SSH failure reason (e.g. 'connection lost', 'channel open failure').
Example fix
// before
client := staleClient // connection already closed
err := connutil.CpWshToRemote(ctx, client, os, arch)
// after
if client == nil || isClosed(client) {
client = reconnect(connName)
}
err := connutil.CpWshToRemote(ctx, client, os, arch) Defensive patterns
Strategy: retry
Validate before calling
// ensure the SSH client is alive before install
timeoutCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()
if _, _, err := genconn.RunSimpleCommand(timeoutCtx, client, genconn.CommandSpec{Cmd: "true"}); err != nil {
return fmt.Errorf("ssh connection not ready: %w", err)
} Try / catch
err := connutil.CpWshToRemote(ctx, client, os, arch)
if err != nil && strings.Contains(err.Error(), "failed to create remote command") {
client = reconnect(connName)
err = connutil.CpWshToRemote(ctx, client, os, arch)
} Prevention
- Ping the remote with a trivial command before long-running install/update flows.
- Reconnect idle SSH sessions before creating exec channels.
- Check sshd MaxSessions/ForceCommand settings on hosts where installs fail.
- Do not reuse client objects after their connection has been closed.
When it happens
Trigger: genconn.MakeSSHCmdClient returns an error: underlying SSH client is disconnected/closed, SSH session allocation fails (server refuses exec), connection dropped between connect and command creation, or the command spec is rejected by the client implementation.
Common situations: SSH session limits (MaxSessions) exhausted on the server; connection idle-timed out just before wsh install/update; server-side restriction (ForceCommand, restricted shell) preventing exec; using a client object after the connection was closed.
Related errors
- error running uname -sm: %w, stderr: %s
- failed to get stdin pipe: %w
- nil wshrpc passed to wshclient
- getting ssh connection status: %w
- file info is required
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/ed8cab402f732a77.
Report an issue: GitHub.