wavetermdev/waveterm · error
failed to copy data: %w
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.
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)
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
- reading input: %w
- failed to copy data: %w (stderr: %s)
- stream file protocol error, first pk fileinfo is empty
- stream file protocol error, directory entry has data
- stream file protocol error, no file info
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/461004e652729916.
Report an issue: GitHub.