wavetermdev/waveterm · error
cannot get info for source file %q: %w
Error message
cannot get info for source file %q: %w
What it means
RemoteFileCopyCommand first issues a RemoteFileInfoCommand RPC to the source host to stat the file being copied. This error wraps any failure of that RPC — the file may not exist, be unreadable, the connection may be down, or the RPC may time out. The wrapper adds the source URI (%q) so the caller knows which path failed; the underlying cause is in the wrapped error.
Source
Thrown at pkg/wshrpc/wshremote/wshremote_file.go:151
if srcConn.Host == destConn.Host {
srcPathCleaned := filepath.Clean(wavebase.ExpandHomeDirSafe(srcConn.Path))
err := remoteCopyFileInternal(data.SrcUri, data.DestUri, srcPathCleaned, destPathCleaned, destHasSlash, opts.Overwrite)
return false, err
}
// FROM external TO here - only supports single file copying
timeout := wshfs.DefaultTimeout
if opts.Timeout > 0 {
timeout = time.Duration(opts.Timeout) * time.Millisecond
}
readCtx, timeoutCancel := context.WithTimeoutCause(ctx, timeout, fmt.Errorf("timeout copying file %q to %q", data.SrcUri, data.DestUri))
defer timeoutCancel()
copyStart := time.Now()
srcFileInfo, err := wshclient.RemoteFileInfoCommand(wshfs.RpcClient, srcConn.Path, &wshrpc.RpcOpts{Timeout: opts.Timeout, Route: wshutil.MakeConnectionRouteId(srcConn.Host)})
if err != nil {
return false, fmt.Errorf("cannot get info for source file %q: %w", data.SrcUri, err)
}
if srcFileInfo.IsDir {
return false, fmt.Errorf("copying directories is not supported")
}
if srcFileInfo.Size > RemoteFileTransferSizeLimit {
return false, fmt.Errorf("file %q size %d exceeds transfer limit of %d bytes", data.SrcUri, srcFileInfo.Size, RemoteFileTransferSizeLimit)
}
destFilePath, err := prepareDestForCopy(destPathCleaned, fspath.Base(srcConn.Path), destHasSlash, opts.Overwrite)
if err != nil {
return false, err
}
destFile, err := os.OpenFile(destFilePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, srcFileInfo.Mode)
if err != nil {
return false, fmt.Errorf("cannot create destination file %q: %w", destFilePath, err)
}
defer destFile.Close()View on GitHub (pinned to a4447c1563)
Solutions
- Verify the source URI exists and is readable on the source host (run `wsh ls` or an equivalent RemoteFileInfoCommand call first).
- Check the connection to the source host is up and routed (MakeConnectionRouteId(srcConn.Host) resolves to a live wsh client).
- Inspect the wrapped cause (%w) to distinguish os.ErrNotExist / permission errors from timeouts and fix accordingly.
- Increase opts.Timeout if large/slow hosts cause RPC timeouts.
Example fix
// before
ok, err := RemoteFileCopyCommand(ctx, wshrpc.CommandFileCopyData{SrcUri: "wsh://host/typo/path.txt", DestUri: "/tmp/out"})
// after
if _, err := wshclient.RemoteFileInfoCommand(rpc, path, &wshrpc.RpcOpts{Route: wshutil.MakeConnectionRouteId(host)}); err != nil {
log.Fatalf("source file missing: %v", err)
}
ok, err := RemoteFileCopyCommand(ctx, wshrpc.CommandFileCopyData{SrcUri: "wsh://host/correct/path.txt", DestUri: "/tmp/out"}) Defensive patterns
Strategy: validation
Validate before calling
info, err := wshclient.RemoteFileInfoCommand(rpc, srcPath, &wshrpc.RpcOpts{Route: wshutil.MakeConnectionRouteId(host), Timeout: 10000})
if err != nil {
return fmt.Errorf("source %q unreachable: %w", srcUri, err)
} Type guard
func sourceFileAvailable(err error) bool { return err == nil } Try / catch
ok, err := RemoteFileCopyCommand(ctx, data)
if err != nil {
if strings.Contains(err.Error(), "cannot get info for source file") {
var pathErr *fs.PathError
if errors.As(err, &pathErr) && errors.Is(pathErr, fs.ErrNotExist) {
// handle missing source
}
}
return err
} Prevention
- Stat the source file with RemoteFileInfoCommand before copying.
- Confirm the source host connection is live before issuing remote RPCs.
- Use exact, verified URIs (wsh ls / tab completion) rather than hand-typed paths.
- Set a reasonable opts.Timeout to fail fast on dead connections.
When it happens
Trigger: Calling wshclient.RemoteFileInfoCommand for srcConn.Path over route MakeConnectionRouteId(srcConn.Host) returns an error: nonexistent source path, permission denied, source connection offline/not routed, or RPC timeout (opts.Timeout or wshfs.DefaultTimeout elapsed).
Common situations: Typo in the source URI; wsh not installed/running on the remote host; SSH connection dropped; copying from a mount (s3:/, wsh://) whose connection is not authenticated; source file deleted between listing and copy.
Related errors
- stream broker route id not available for file copy
- create block failed: %v
- running view command: %w
- opening secrets UI: %w
- getting block info: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/caa4866fc22ea31f.
Report an issue: GitHub.