{"record":{"id":"93f3041cff26bf45","repo":"can1357/oh-my-pi","slug":"and-are-the-same-file","errorCode":null,"errorMessage":"{} and {} are the same file","messagePattern":"(.+?) and (.+?) are the same file","errorType":"error_code","errorClass":"LnError","httpStatus":null,"severity":"error","filePath":"crates/pi-builtins/src/ln.rs","lineNumber":59,"sourceCode":"\tverbose:        bool,\n}\n\n#[derive(Clone, Debug, Eq, PartialEq)]\nenum OverwriteMode {\n\tNoClobber,\n\tInteractive,\n\tForce,\n}\n\n#[derive(Error, Debug)]\nenum LnError {\n\t#[error(\"target {} is not a directory\", _0.quote())]\n\tTargetIsNotADirectory(PathBuf),\n\n\t#[error(\"\")]\n\tSomeLinksFailed,\n\n\t#[error(\"{} and {} are the same file\", _0.quote(), _1.quote())]\n\tSameFile(PathBuf, PathBuf),\n\n\t#[error(\"missing destination file operand after {}\", _0.quote())]\n\tMissingDestination(PathBuf),\n\n\t#[error(\"extra operand {}\\nTry '{} --help' for more information.\", _0.quote(), _1)]\n\tExtraOperand(OsString, String),\n\n\t#[error(\"{}: hard link not allowed for directory\", _0.to_string_lossy())]\n\tFailedToCreateHardLinkDir(PathBuf),\n\n\t#[error(\"{0}\")]\n\tMessage(String),\n\n\t#[error(\"{0}\")]\n\tIo(#[from] std::io::Error),\n}\n","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/crates/pi-builtins/src/ln.rs#L41-L77","documentation":"The ln builtin's SameFile variant fires when the source and destination operands resolve to the same file. Creating a hard link or symlink to itself would either fail at the OS level or create a pointless self-referential link, so the tool rejects it up front with a GNU-coreutils-style message naming both quoted paths.","triggerScenarios":"Calling ln where source and destination are the same path (after canonicalization), e.g. `ln file.txt file.txt` or `ln dir/a dir/a`.","commonSituations":"Shell/variable interpolation mistakes where SRC and DST variables expand to the same value; scripts copying a file onto itself via a loop or config substitution.","solutions":["Check that source and destination paths differ before invoking ln","Use std::fs::canonicalize on both paths and compare before linking","Fix the variable/script that supplies identical operands"],"exampleFix":"// before\nln(&host, &[\"file.txt\", \"file.txt\"])?;\n// after\nif std::fs::canonicalize(\"file.txt\")? == std::fs::canonicalize(\"file.txt\")? {\n    eprintln!(\"source and destination are the same file\");\n} else {\n    ln(&host, &[\"file.txt\", \"file.txt\"])?;\n}","handlingStrategy":"validation","validationCode":"fn ensure_distinct(src: &Path, dst: &Path) -> std::io::Result<()> {\n    if src == dst || std::fs::canonicalize(src)? == std::fs::canonicalize(dst)? {\n        return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, \"source and destination are the same file\"));\n    }\n    Ok( )\n}","typeGuard":null,"tryCatchPattern":"match ln(&host, args) {\n    Err(e) if e.to_string().contains(\"are the same file\") => eprintln!(\"skip: source == destination\"),\n    other => other?,\n}","preventionTips":["Compare canonicalized paths before any link operation","Avoid reusing the same variable for source and destination in scripts"],"tags":["filesystem","hardlink","argument-error"],"backgroundTag":"source-and-destination-same-file","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}