wavetermdev/waveterm · error
error copying file %q to %q: %w
Error message
error copying file %q to %q: %w
What it means
RemoteFileCopyCommand wraps any error returned by io.Copy(destFile, reader), which transfers bytes from the remote read stream into the destination file. This means the stream started successfully but data transfer failed mid-copy (network interruption, read/write I/O error).
Source
Thrown at pkg/wshrpc/wshremote/wshremote_file.go:190
return false, fmt.Errorf("stream broker route id not available for file copy")
}
writerRouteId := wshutil.MakeConnectionRouteId(srcConn.Host)
reader, streamMeta := wshfs.RpcClient.StreamBroker.CreateStreamReader(wshfs.RpcClientRouteId, writerRouteId, 256*1024)
log.Printf("RemoteFileCopyCommand: readroute=%s writeroute=%s", streamMeta.ReaderRouteId, streamMeta.WriterRouteId)
defer reader.Close()
go func() {
<-readCtx.Done()
reader.Close()
}()
streamData := wshrpc.CommandRemoteFileStreamData{
Path: srcConn.Path,
StreamMeta: *streamMeta,
}
if _, err = wshclient.RemoteFileStreamCommand(wshfs.RpcClient, streamData, &wshrpc.RpcOpts{Route: writerRouteId}); err != nil {
return false, fmt.Errorf("error starting file stream for %q: %w", data.SrcUri, err)
}
if _, err = io.Copy(destFile, reader); err != nil {
return false, fmt.Errorf("error copying file %q to %q: %w", data.SrcUri, data.DestUri, err)
}
totalTime := time.Since(copyStart).Seconds()
totalMegaBytes := float64(srcFileInfo.Size) / 1024 / 1024
rate := float64(0)
if totalTime > 0 {
rate = totalMegaBytes / totalTime
}
log.Printf("RemoteFileCopyCommand: done; 1 file copied in %.3fs, total of %.4f MB, %.2f MB/s\n", totalTime, totalMegaBytes, rate)
return false, nil
}
func (impl *ServerImpl) RemoteListEntriesCommand(ctx context.Context, data wshrpc.CommandRemoteListEntriesData) chan wshrpc.RespOrErrorUnion[wshrpc.CommandRemoteListEntriesRtnData] {
ch := make(chan wshrpc.RespOrErrorUnion[wshrpc.CommandRemoteListEntriesRtnData], 16)
go func() {
defer func() {
panichandler.PanicHandler("RemoteListEntriesCommand", recover())
}()View on GitHub (pinned to a4447c1563)
Solutions
- Check the wrapped error for network vs. local I/O causes.
- Verify destination disk space and write permissions.
- Re-run the copy; consider deleting a partial destination file first.
- For large/unstable transfers, ensure the connection is stable or use a resumable approach.
Example fix
// before
_, err := wshclient.RemoteFileCopyCommand(ctx, copyData, nil)
// after
err := wshclient.RemoteFileCopyCommand(ctx, copyData, nil)
if err != nil && strings.Contains(err.Error(), "error copying file") {
_ = os.Remove(destPath) // clean partial file
err = wshclient.RemoteFileCopyCommand(ctx, copyData, nil)
} Defensive patterns
Strategy: retry
Validate before calling
info, err := wshclient.RemoteFileInfoCommand(ctx, srcUri, nil)
if err != nil { return err }
// check dest has enough space if size known
_ = info.Size Try / catch
for attempt := 0; attempt < 3; attempt++ {
err := wshclient.RemoteFileCopyCommand(ctx, data, nil)
if err == nil { break }
if strings.Contains(err.Error(), "error copying file") {
_ = os.Remove(destPath); time.Sleep(backoff(attempt)); continue
}
return err
} Prevention
- Remove partial destination files after failed copies
- Monitor network stability for large transfers
- Check destination free space before copying
When it happens
Trigger: io.Copy fails during RemoteFileCopyCommand: the read side (remote stream) errors out, the destination write fails (disk full, permission), or the RPC stream breaks while transferring.
Common situations: Large file transfer over a flaky SSH/network connection; destination disk quota exceeded; destination directory became unwritable after the copy began.
Related errors
- failed to copy data: %w
- reading file stream: %w
- error starting file stream for %q: %w
- cannot call ${methodName}: no web endpoint
- call ${methodName} failed: ${resp.status} ${resp.statusText}
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/b7f4bb41e5f1a57e.
Report an issue: GitHub.