sinelaw/fresh · error · io::Error (InvalidInput)

Cannot paste a directory into itself

Error message

Cannot paste a directory into itself

What it means

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.

Solutions

  1. Choose a destination outside the source directory subtree
  2. Check dst.starts_with(src) for directories in caller code before issuing the paste and show the user a message
  3. For duplicates, generate a sibling name instead of a nested one

Example fix

// before
explorer.paste(src_dir, src_dir.join("copy"))?; // InvalidInput
// after
let dst = src_dir.parent().unwrap().join(format!("{} copy", src_dir.file_name().unwrap().to_string_lossy()));
explorer.paste(src_dir, dst)?;
Defensive patterns

Strategy: validation

Validate before calling

fn paste_is_safe(src: &Path, dst: &Path, src_is_dir: bool) -> bool {
    !src_is_dir || !dst.starts_with(src)
}

Try / catch

match explorer.paste(src, dst) { Err(e) if e.kind() == io::ErrorKind::InvalidInput => ui.show_message("Cannot paste a folder into itself"), other => other?, }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13). Data as JSON: /api/errors/6694fd6aab76dd2c. Report an issue: GitHub.

Appendix: source

Thrown at crates/fresh-editor/src/app/file_explorer.rs:1310

        }
        self.active_window_mut().key_context = KeyContext::FileExplorer;
    }

    /// Move or copy a single item at the filesystem level. No tree or UI
    /// state is touched — callers are responsible for refreshing the
    /// explorer afterwards.
    fn paste_one_fs_op(&self, src: &Path, dst: &Path, is_cut: bool) -> PasteOpOutcome {
        let src_is_dir = self.authority().filesystem.is_dir(src).unwrap_or(false);

        // Guard against pasting a directory into itself or into one of its
        // own descendants. Without this, `copy_dir_all(/d, /d/d)` would
        // create `/d/d`, then iterate `/d` — which now contains the
        // just-created `/d/d` — and recurse forever until stack overflow
        // or disk-full. The check applies only when the source is a
        // directory; file-into-itself is already handled by the
        // same-location check in `file_explorer_paste`.
        if src_is_dir && dst.starts_with(src) {
            return PasteOpOutcome::Failed(std::io::Error::new(
                std::io::ErrorKind::InvalidInput,
                "Cannot paste a directory into itself",
            ));
        }

        if is_cut {
            // Try rename first (works if same filesystem). Only fall back to
            // copy+delete for cross-device errors — any other rename failure
            // (permission denied, etc.) must surface as-is so we don't
            // silently succeed via a different codepath.
            match self.authority().filesystem.rename(src, dst) {
                Ok(()) => PasteOpOutcome::Ok,
                Err(e) if e.kind() == std::io::ErrorKind::CrossesDevices => {
                    let copy_result = if src_is_dir {
                        self.authority().filesystem.copy_dir_all(src, dst)
                    } else {
                        self.authority().filesystem.copy(src, dst).map(|_| ())
                    };

View on GitHub (pinned to 67894ca546)