{"record":{"id":"e45e85f6007ab643","repo":"denoland/deno","slug":"source-and-destination-paths-refer-to-the-same-fil","errorCode":null,"errorMessage":"Source and destination paths refer to the same file","messagePattern":"Source and destination paths refer to the same file","errorType":"exception","errorClass":"FsError","httpStatus":null,"severity":"error","filePath":"ext/fs/std_fs.rs","lineNumber":664,"sourceCode":"\n  res.map_err(Into::into)\n}\n\nfn copy_file(from: &Path, to: &Path) -> FsResult<()> {\n  // Guard against copying a file onto itself. Otherwise the destination is\n  // opened with truncation (or unlinked) before the source is read, which\n  // silently empties the file. Match `cp` behavior and error instead.\n  //\n  // `same_file::is_same_file` compares the file identity (device + inode on\n  // Unix, file index + volume serial via the open handle on Windows) using a\n  // single stat per path, rather than fully canonicalizing both paths which\n  // would `lstat`/`readlink` every component twice. It still catches\n  // equivalent paths such as `./`, `..`, symlinks and hard links, and returns\n  // `Err` (treated as \"not the same file\") in the common case where the\n  // destination does not yet exist.\n  if same_file::is_same_file(from, to).unwrap_or(false) {\n    return Err(\n      io::Error::new(\n        io::ErrorKind::InvalidInput,\n        \"Source and destination paths refer to the same file\",\n      )\n      .into(),\n    );\n  }\n\n  #[cfg(target_os = \"macos\")]\n  {\n    use std::ffi::CString;\n    use std::os::unix::fs::OpenOptionsExt;\n    use std::os::unix::fs::PermissionsExt;\n\n    use libc::clonefile;\n    use libc::stat;\n    use libc::unlink;\n\n    let from_str = CString::new(from.as_os_str().as_encoded_bytes())","sourceCodeStart":646,"sourceCodeEnd":682,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/fs/std_fs.rs#L646-L682","documentation":"copy_file() guards against copying a file onto itself: opening the destination with truncation before reading the source would silently empty the file, so Deno compares file identity with same_file::is_same_file (device + inode on Unix, file index + volume serial on Windows) and, if identical, returns io::ErrorKind::InvalidInput 'Source and destination paths refer to the same file' — matching cp behavior and libuv's message.","triggerScenarios":"Deno.copyFileSync('a.txt', 'a.txt'); destination is a symlink or hard link resolving to the source inode (copyFileSync('a.txt', 'link-to-a.txt')); equivalent spellings like './a.txt' vs 'a.txt'; paths through symlinked directories that land on the same file.","commonSituations":"Backup scripts whose glob results include the destination; FROM/TO parameters mistakenly set to the same value; symlinked config or cache directories making two different strings the same file.","solutions":["Compare resolved paths first: skip when Deno.realPathSync(from) === Deno.realPathSync(to)","Skip the call when the two argument strings are equal","If you intended an overwrite workflow, delete the destination explicitly instead of copying onto itself","Audit symlink/hardlink layouts when from and to look different but resolve identically"],"exampleFix":"// before\nDeno.copyFileSync(fromPath, toPath);\n\n// after\nif (Deno.realPathSync(fromPath) !== Deno.realPathSync(toPath)) {\n  Deno.copyFileSync(fromPath, toPath);\n}","handlingStrategy":"validation","validationCode":"function copyFileSyncIfDifferent(from: string, to: string): void {\n  let fromReal: string, toReal: string;\n  try {\n    fromReal = Deno.realPathSync(from);\n  } catch {\n    throw new Error(`Source does not exist: ${from}`);\n  }\n  try {\n    toReal = Deno.realPathSync(to);\n  } catch {\n    Deno.copyFileSync(from, to); // destination absent: safe\n    return;\n  }\n  if (fromReal === toReal) return; // same inode: skip\n  Deno.copyFileSync(from, to);\n}","typeGuard":"function isSamePath(from: string, to: string): boolean {\n  try {\n    return Deno.realPathSync(from) === Deno.realPathSync(to);\n  } catch {\n    return false; // missing destination cannot be the same file\n  }\n}","tryCatchPattern":"try {\n  Deno.copyFileSync(from, to);\n} catch (e) {\n  if (e instanceof Error && /refer to the same file/.test(e.message)) return;\n  throw e;\n}","preventionTips":["Compare realPathSync of both arguments before copying","Validate FROM/TO parameters (env vars, CLI args) are distinct strings","Remember hard links and symlinks resolve to the same inode — path equality checks are not enough"],"tags":["filesystem","copy","same-file","hardlink","symlink","invalid-input"],"backgroundTag":"copy-same-file","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}