{"record":{"id":"093b0666c3225f29","repo":"yorukot/superfile","slug":"failed-to-remove-source-after-move-w","errorCode":null,"errorMessage":"failed to remove source after move: %w","messagePattern":"failed to remove source after move: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/internal/file_operations.go","lineNumber":195,"sourceCode":"\t\t}\n\n\t\trelPath, err := filepath.Rel(src, path)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tnewPath := filepath.Join(dst, relPath)\n\t\treturn actualPasteOperation(info, path, newPath, cut, sameDev, p, processBarModel)\n\t})\n\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// If this was a cut operation and we had to do a manual copy, remove the source\n\tif cut && !sameDev {\n\t\terr = os.RemoveAll(src)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to remove source after move: %w\", err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc actualPasteOperation(info os.FileInfo, path string, newPath string, cut bool, sameDev bool,\n\tp *processbar.Process, processBarModel *processbar.Model) error {\n\tvar err error\n\tif info.IsDir() {\n\t\t// TODO - this is likely not needed because we did\n\t\t// dst, err := renameIfDuplicate(dst) above\n\t\tnewPath, err = renameIfDuplicate(newPath)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\terr = os.MkdirAll(newPath, info.Mode())\n\t\treturn err","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/yorukot/superfile/blob/b72f550bc6e75913f48eb49fdd258e1a2df2fe88/src/internal/file_operations.go#L177-L213","documentation":"pasteDir wraps os.RemoveAll(src) failures when finishing a cross-device cut (move) that fell back to a manual copy. The move copied successfully but cleanup of the original failed, so the source remains and the wrapped cause (usually EPERM/EBUSY/ENOTEMPTY) is reported.","triggerScenarios":"A cut-paste across filesystems (rename fails EXDEV, so pasteDir does copy+delete) where the source cannot be removed: a file inside is held open (EBUSY on Windows), permission denied, or a new file appeared in the source dir making it non-empty for a non-recursive failure.","commonSituations":"Moving directories between drives/partitions (e.g. home -> USB) while an editor or indexer holds files open; moving dirs with files owned by other users; Windows AV scanners locking files.","solutions":["Close applications holding files in the source directory open (editors, indexers, terminals cd'd into it), then retry the move.","Check write/execute permissions on the source directory and its contents (chmod -R u+w).","Remove the leftover source manually once unlocked: rm -rf <src> (verify the copy first).","Same-device moves avoid this path entirely: paste onto the same filesystem so rename() is used instead of copy+delete."],"exampleFix":"// before\nif cut && !sameDev {\n    err = os.RemoveAll(src)\n    if err != nil {\n        return fmt.Errorf(\"failed to remove source after move: %w\", err)\n    }\n}\n// after\nif cut && !sameDev {\n    if err := os.RemoveAll(src); err != nil {\n        return fmt.Errorf(\"move succeeded but could not delete source %s (is a file open elsewhere?): %w\", src, err)\n    }\n}","handlingStrategy":"try-catch","validationCode":"// cross-device move will copy+delete; make sure no process holds the tree\n// (best effort) verify write access to source root\nif f, err := os.OpenFile(src, os.O_RDONLY, 0); err != nil {\n    return fmt.Errorf(\"source may not be removable: %w\", err)\n} else {\n    f.Close()\n}","typeGuard":null,"tryCatchPattern":"if err := ops.Paste(src, dst, cut=true); err != nil {\n    if strings.Contains(err.Error(), \"failed to remove source after move\") {\n        // copy succeeded; ask user to close apps holding source files, then rm -rf manually\n    }\n    return err\n}","preventionTips":["Move within the same filesystem when possible so rename() is used.","Close editors/indexers before cross-device moves.","Verify the copied destination before deleting the source manually."],"tags":["go","filesystem","move","removeall"],"backgroundTag":"file-delete-failed","analyzedSha":"b72f550bc6e75913f48eb49fdd258e1a2df2fe88","analyzedAt":"2026-09-01T04:38:08.254Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}