{"record":{"id":"7e50a1320264aaa7","repo":"wavetermdev/waveterm","slug":"failed-to-start-remote-command-w","errorCode":null,"errorMessage":"failed to start remote command: %w","messagePattern":"failed to start remote command: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/remote/connutil.go","lineNumber":140,"sourceCode":"\t}\n\tblocklogger.Infof(ctx, \"[conndebug] copying %q to remote server %q\\n\", wshLocalPath, wavebase.RemoteFullWshBinPath)\n\tgenCmd, err := genconn.MakeSSHCmdClient(client, genconn.CommandSpec{\n\t\tCmd: installCmd.String(),\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create remote command: %w\", err)\n\t}\n\tstdin, err := genCmd.StdinPipe()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get stdin pipe: %w\", err)\n\t}\n\tdefer stdin.Close()\n\tstderrBuf, err := genconn.MakeStderrSyncBuffer(genCmd)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get stderr pipe: %w\", err)\n\t}\n\tif err := genCmd.Start(); err != nil {\n\t\treturn fmt.Errorf(\"failed to start remote command: %w\", err)\n\t}\n\tcopyDone := make(chan error, 1)\n\tgo func() {\n\t\tdefer close(copyDone)\n\t\tdefer stdin.Close()\n\t\tif _, err := io.Copy(stdin, input); err != nil && err != io.EOF {\n\t\t\tcopyDone <- fmt.Errorf(\"failed to copy data: %w\", err)\n\t\t} else {\n\t\t\tcopyDone <- nil\n\t\t}\n\t}()\n\tprocErr := genconn.ProcessContextWait(ctx, genCmd)\n\tif procErr != nil {\n\t\treturn fmt.Errorf(\"remote command failed: %w (stderr: %s)\", procErr, stderrBuf.String())\n\t}\n\tcopyErr := <-copyDone\n\tif copyErr != nil {\n\t\treturn fmt.Errorf(\"failed to copy data: %w (stderr: %s)\", copyErr, stderrBuf.String())","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/remote/connutil.go#L122-L158","documentation":"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.","triggerScenarios":"UpdateWsh/InstallWsh invoking CpWshToRemote when the SSH session cannot start the remote process — dead connection, remote shell unavailable, or invalid command construction.","commonSituations":"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.","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"],"exampleFix":"// before\nerr := CpWshToRemote(ctx, conn, input, \"/bad/path/wsh\")\n// after\ndest := filepath.Join(\"/usr/local/bin\", \"wsh\") // validate dest exists & writable\nerr := CpWshToRemote(ctx, conn, input, dest)","handlingStrategy":"retry","validationCode":"if conn == nil || conn.IsClosed() {\n    return fmt.Errorf(\"remote connection not available\")\n}\nif dest == \"\" { return fmt.Errorf(\"empty destination path\") }","typeGuard":"func connReady(c *remote.Conn) bool { return c != nil && !c.IsClosed() }","tryCatchPattern":"err := CpWshToRemote(ctx, conn, input, dest)\nif err != nil && strings.Contains(err.Error(), \"failed to start remote command\") {\n    time.Sleep(time.Second); conn = reconnect(ctx)\n    err = CpWshToRemote(ctx, conn, input, dest)\n}","preventionTips":["Verify remote shell path in config","Ensure destination dir exists and is writable","Confirm disk space on remote before large installs"],"tags":["go","ssh","process"],"backgroundTag":"remote-command-start-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}