wavetermdev/waveterm · error
failed to copy data
Error message
failed to copy data: %w
What it means
Inside CpWshToRemote a goroutine io.Copy's the local input into the remote command's stdin. Any copy failure other than io.EOF is wrapped with this message and surfaced after the process wait completes.
Solutions
- Retry the operation after confirming the remote connection is stable
- Check remote stderr (this variant has no stderr suffix, so it likely failed before process wait) and reconnect if the channel closed
- Verify the local input source is readable for the whole transfer
- Use a matching wsh version on both ends
Example fix
// before
f, _ := os.Open(binPath)
err := CpWshToRemote(ctx, conn, f, dest)
// after
f, err := os.Open(binPath)
if err != nil { return err }
defer f.Close()
if fi, statErr := f.Stat(); statErr != nil || !fi.Mode().IsRegular() {
return fmt.Errorf("invalid input file")
}
err = CpWshToRemote(ctx, conn, f, dest) Defensive patterns
Strategy: try-catch
Validate before calling
fi, err := input.Stat()
if err != nil || !fi.Mode().IsRegular() {
return fmt.Errorf("input must be a readable regular file")
} Try / catch
err := CpWshToRemote(ctx, conn, input, dest)
if err != nil && strings.Contains(err.Error(), "failed to copy data") {
// check input source integrity, then retry once
input.Seek(0, io.Start); err = CpWshToRemote(ctx, conn, input, dest)
} Prevention
- Open input files fully before transfer; avoid streaming from unstable sources
- Don't mutate or delete the input during copy
- Keep SSH sessions alive; avoid aggressive idle timeouts
When it happens
Trigger: The local reader (input) errors mid-stream, or the remote stdin pipe closes prematurely (remote process died before consuming all data) during UpdateWsh/InstallWsh.
Common situations: Remote wsh process crashed or was killed mid-transfer; network interruption breaking the SSH channel; local file being read changed/vanished during copy.
Related errors
- error copying file to
- Error reading request body
- error writing osc message (AdaptMsgChToPty)
- error writing to output (AdaptOutputChToStream)
- error writing trailing newline to output…
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/461004e652729916.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/remote/connutil.go:147
}
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())
}
return nil
}
func IsPowershell(shellPath string) bool {
// get the base path, and then check contains
shellBase := filepath.Base(shellPath)View on GitHub (pinned to a4447c1563)