{"record":{"id":"c6b5223e1f7ee6f4","repo":"nikivdev/code","slug":"refusing-to-overwrite-c6b522","errorCode":null,"errorMessage":"Refusing to overwrite {}","messagePattern":"Refusing to overwrite (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/code.rs","lineNumber":857,"sourceCode":"        err.raw_os_error() == Some(libc::EXDEV)\n    }\n    #[cfg(not(unix))]\n    {\n        let _ = err;\n        false\n    }\n}\n\nfn copy_dir_all(from: &Path, to: &Path) -> Result<()> {\n    fs::create_dir_all(to).with_context(|| format!(\"failed to create {}\", to.display()))?;\n    for entry in fs::read_dir(from).with_context(|| format!(\"failed to read {}\", from.display()))? {\n        let entry = entry?;\n        let path = entry.path();\n        let file_type = entry.file_type()?;\n        let target = to.join(entry.file_name());\n\n        if target.exists() {\n            bail!(\"Refusing to overwrite {}\", target.display());\n        }\n\n        if file_type.is_dir() {\n            copy_dir_all(&path, &target)?;\n        } else if file_type.is_file() {\n            fs::copy(&path, &target)\n                .with_context(|| format!(\"failed to copy {}\", path.display()))?;\n        } else if file_type.is_symlink() {\n            let link_target = fs::read_link(&path)\n                .with_context(|| format!(\"failed to read link {}\", path.display()))?;\n            copy_symlink(&link_target, &target)?;\n        }\n    }\n    Ok(())\n}\n\nfn copy_symlink(target: &Path, dest: &Path) -> Result<()> {\n    #[cfg(unix)]","sourceCodeStart":839,"sourceCodeEnd":875,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/code.rs#L839-L875","documentation":"copy_dir_all recursively copies a directory tree, and before writing each entry it checks whether the corresponding target path already exists, bailing with 'Refusing to overwrite <path>' if so. This is an explicit non-destructive guarantee: the copier never clobbers existing files or directories, and it fails at the first collision instead of merging silently.","triggerScenarios":"Calling any of copy_dir_all's callers (new_from_template, new_project, migrate_project, migrate_to_path, move_dir, or copy_dir_all recursively) when the destination tree already contains any file or directory that the source tree would create — including a partially-created target left by a previous failed run (copy_dir_all recurses into itself, so a retry after a mid-copy failure hits this on the leftover files).","commonSituations":"Re-running `new` with a template into an existing folder; retrying a migration that crashed halfway, leaving partial output; template files colliding with files created by ensure_dir/other steps; case-insensitive filesystems colliding on names differing only by case.","solutions":["Delete or move the existing destination directory, then re-run the copy.","Choose a fresh target path that does not exist.","If a previous run failed midway, remove the partial output first — the copier is not resumable.","Compare source and destination trees beforehand (e.g. `rsync -n`) to find which entries collide."],"exampleFix":"// before\ncopy_dir_all(&template, &target)?; // target/config.toml already exists\n// after\nif target.exists() {\n    fs::remove_dir_all(&target)?; // or pick a new target\n}\ncopy_dir_all(&template, &target)?;","handlingStrategy":"try-catch","validationCode":"fn target_is_clear(src: &Path, dst: &Path) -> bool {\n    !dst.exists() || !walkdir::WalkDir::new(src).into_iter().any(|e| {\n        e.map(|e| dst.join(e.file_name()).exists()).unwrap_or(true)\n    })\n}","typeGuard":null,"tryCatchPattern":"match copy_dir_all(src, dst) {\n    Err(e) if e.to_string().starts_with(\"Refusing to overwrite\") => {\n        let path = e.to_string().trim_start_matches(\"Refusing to overwrite \");\n        eprintln!(\"Collision at {path}: remove the existing destination and retry.\");\n    }\n    other => other?,\n}","preventionTips":["Ensure the destination directory is empty (or absent) before copying.","After a failed copy, delete the partial output before retrying — retries are not resumable.","Pick unique target names (timestamps, hashes) for repeated template instantiations."],"tags":["filesystem","overwrite-protection","copy","idempotency"],"backgroundTag":"refusing-to-overwrite-existing-file","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}