{"record":{"id":"6694fd6aab76dd2c","repo":"sinelaw/fresh","slug":"cannot-paste-a-directory-into-itself","errorCode":null,"errorMessage":"Cannot paste a directory into itself","messagePattern":"Cannot paste a directory into itself","errorType":"exception","errorClass":"io::Error (InvalidInput)","httpStatus":null,"severity":"error","filePath":"crates/fresh-editor/src/app/file_explorer.rs","lineNumber":1310,"sourceCode":"        }\n        self.active_window_mut().key_context = KeyContext::FileExplorer;\n    }\n\n    /// Move or copy a single item at the filesystem level. No tree or UI\n    /// state is touched — callers are responsible for refreshing the\n    /// explorer afterwards.\n    fn paste_one_fs_op(&self, src: &Path, dst: &Path, is_cut: bool) -> PasteOpOutcome {\n        let src_is_dir = self.authority().filesystem.is_dir(src).unwrap_or(false);\n\n        // Guard against pasting a directory into itself or into one of its\n        // own descendants. Without this, `copy_dir_all(/d, /d/d)` would\n        // create `/d/d`, then iterate `/d` — which now contains the\n        // just-created `/d/d` — and recurse forever until stack overflow\n        // or disk-full. The check applies only when the source is a\n        // directory; file-into-itself is already handled by the\n        // same-location check in `file_explorer_paste`.\n        if src_is_dir && dst.starts_with(src) {\n            return PasteOpOutcome::Failed(std::io::Error::new(\n                std::io::ErrorKind::InvalidInput,\n                \"Cannot paste a directory into itself\",\n            ));\n        }\n\n        if is_cut {\n            // Try rename first (works if same filesystem). Only fall back to\n            // copy+delete for cross-device errors — any other rename failure\n            // (permission denied, etc.) must surface as-is so we don't\n            // silently succeed via a different codepath.\n            match self.authority().filesystem.rename(src, dst) {\n                Ok(()) => PasteOpOutcome::Ok,\n                Err(e) if e.kind() == std::io::ErrorKind::CrossesDevices => {\n                    let copy_result = if src_is_dir {\n                        self.authority().filesystem.copy_dir_all(src, dst)\n                    } else {\n                        self.authority().filesystem.copy(src, dst).map(|_| ())\n                    };","sourceCodeStart":1292,"sourceCodeEnd":1328,"githubUrl":"https://github.com/sinelaw/fresh/blob/67894ca5463dbd7a89bb31add4627c27d6b79d83/crates/fresh-editor/src/app/file_explorer.rs#L1292-L1328","documentation":"paste_one_fs_op refuses to copy/cut a directory into a destination located inside the source directory itself. If allowed, the paste loop would copy the source into its own subtree it is currently iterating, recursing forever until stack overflow or disk-full. It returns io::ErrorKind::InvalidInput with this message.","triggerScenarios":"Calling execute_resolved_multi_paste, perform_file_explorer_paste, or file_explorer_duplicate where the destination path starts_with the source path and the source is a directory — e.g. copying /data and pasting into /data/sub, or duplicating a folder into itself.","commonSituations":"User drags a folder into one of its own subfolders in the file explorer; paste target resolved to a path inside the copied tree; scripted bulk paste with generated destination paths.","solutions":["Choose a destination outside the source directory subtree","Check dst.starts_with(src) for directories in caller code before issuing the paste and show the user a message","For duplicates, generate a sibling name instead of a nested one"],"exampleFix":"// before\nexplorer.paste(src_dir, src_dir.join(\"copy\"))?; // InvalidInput\n// after\nlet dst = src_dir.parent().unwrap().join(format!(\"{} copy\", src_dir.file_name().unwrap().to_string_lossy()));\nexplorer.paste(src_dir, dst)?;","handlingStrategy":"validation","validationCode":"fn paste_is_safe(src: &Path, dst: &Path, src_is_dir: bool) -> bool {\n    !src_is_dir || !dst.starts_with(src)\n}","typeGuard":null,"tryCatchPattern":"match explorer.paste(src, dst) { Err(e) if e.kind() == io::ErrorKind::InvalidInput => ui.show_message(\"Cannot paste a folder into itself\"), other => other?, }","preventionTips":["Validate destination is not inside source before initiating any directory copy","In UI, disable drop targets that are descendants of the drag source","For duplicates, always generate sibling paths, never nested ones"],"tags":["filesystem","paste","recursion","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"67894ca5463dbd7a89bb31add4627c27d6b79d83","analyzedAt":"2026-09-13T15:04:03.701Z","contentChangedAt":"2026-09-13T15:04:03.701Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}