{"record":{"id":"36d9420533c51b0f","repo":"wavetermdev/waveterm","slug":"cannot-copy-q-to-q-w","errorCode":null,"errorMessage":"cannot copy %q to %q: %w","messagePattern":"cannot copy %q to %q: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/remote/fileshare/wshfs/wshfs.go","lineNumber":233,"sourceCode":"\nfunc Move(ctx context.Context, data wshrpc.CommandFileCopyData) error {\n\topts := data.Opts\n\tif opts == nil {\n\t\topts = &wshrpc.FileCopyOpts{}\n\t}\n\tlog.Printf(\"Move: srcuri: %v, desturi: %v, opts: %v\", data.SrcUri, data.DestUri, opts)\n\tsrcConn, err := parseConnection(ctx, data.SrcUri)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error parsing source connection: %w\", err)\n\t}\n\tdestConn, err := parseConnection(ctx, data.DestUri)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error parsing destination connection: %w\", err)\n\t}\n\tif srcConn.Host != destConn.Host {\n\t\tisDir, err := copyInternal(srcConn, destConn, opts)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"cannot copy %q to %q: %w\", data.SrcUri, data.DestUri, err)\n\t\t}\n\t\treturn delete_(srcConn, opts.Recursive && isDir)\n\t}\n\treturn moveInternal(srcConn, destConn, opts)\n}\n\nfunc Copy(ctx context.Context, data wshrpc.CommandFileCopyData) error {\n\topts := data.Opts\n\tif opts == nil {\n\t\topts = &wshrpc.FileCopyOpts{}\n\t}\n\tlog.Printf(\"Copy: srcuri: %v, desturi: %v, opts: %v\", data.SrcUri, data.DestUri, opts)\n\tsrcConn, err := parseConnection(ctx, data.SrcUri)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error parsing source connection: %w\", err)\n\t}\n\tdestConn, err := parseConnection(ctx, data.DestUri)\n\tif err != nil {","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/remote/fileshare/wshfs/wshfs.go#L215-L251","documentation":"wshfs.Move wraps copyInternal failures with 'cannot copy %q to %q'. When Move is asked to move a file across two DIFFERENT hosts, the library cannot do a remote rename, so it falls back to copy-then-delete; this error means the copy half failed and the source was left intact (the delete step never ran). The wrapped error from copyInternal identifies the actual cause (permissions, missing file, timeout, etc.).","triggerScenarios":"Calling wshfs.Move (via FileMoveCommand) where srcConn.Host != destConn.Host and the underlying read/write transfer (copyInternal) fails — e.g. read permission denied on source, write failure on destination, or RPC timeout during the streaming copy.","commonSituations":"Dragging a file from a local block to an SSH remote in Wave when the remote filesystem is read-only or full; moving between two different remote connections; large files exceeding copy timeouts (opts.Timeout too small).","solutions":["Inspect the wrapped copyInternal error to find the real cause (permissions, disk space, timeout).","Increase FileCopyOpts.Timeout if the transfer is timing out on large files.","Verify read access on the source host and write access on the destination host for the given paths.","If cross-host move is not intended, ensure both URIs use the same connection host so Move uses the plain remote rename path (moveInternal)."],"exampleFix":"// before\nMove(ctx, wshrpc.CommandFileCopyData{SrcUri: \"conn:local:///a\", DestUri: \"conn:myserver://b\"}) // no timeout\n// after\nMove(ctx, wshrpc.CommandFileCopyData{SrcUri: \"conn:local:///a\", DestUri: \"conn:myserver://b\", Opts: &wshrpc.FileCopyOpts{Timeout: 60000}})","handlingStrategy":"try-catch","validationCode":"src, _ := connparse.ParseConnection(ctx, data.SrcUri)\ndst, _ := connparse.ParseConnection(ctx, data.DestUri)\nif src.Host != dst.Host { /* cross-host: expect copy fallback, set generous timeout */ }","typeGuard":null,"tryCatchPattern":"if err := wshfs.Move(ctx, data); err != nil {\n    if strings.Contains(err.Error(), \"cannot copy\") {\n        // unwrap copyInternal cause, retry with larger timeout or fix permissions\n    }\n}","preventionTips":["Set a generous FileCopyOpts.Timeout for cross-host moves of large files.","Check source read and destination write permissions before moving.","Prefer same-host URIs when a plain rename is intended."],"tags":["file-transfer","copy","go"],"backgroundTag":"file-copy-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}