{"record":{"id":"b47fcfe030d67cd0","repo":"jdx/mise","slug":"rename-exe-cannot-rename-to-target-alr","errorCode":null,"errorMessage":"rename_exe: cannot rename '{}' to '{}': target already exists. Check for duplicate or overlapping rename_exe mappings.","messagePattern":"rename_exe: cannot rename '(.+?)' to '(.+?)': target already exists\\. Check for duplicate or overlapping rename_exe mappings\\.","errorType":"exception","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/backend/static_helpers.rs","lineNumber":1169,"sourceCode":"}\n\n/// Renames `path` (named `file_name`) to `target` within `dir`, preserving any\n/// required extension and ensuring the result is executable. A collision on the\n/// target (two mappings pointing at the same name, or the archive already\n/// containing that name) is unsatisfiable, so it fails the install loudly rather\n/// than silently dropping a binary and reporting success.\nfn finish_rename(dir: &Path, path: &Path, file_name: &str, target: &str) -> eyre::Result<()> {\n    let target_path = keep_required_extensions(dir, file_name, target, dir.join(target));\n    // Ensure the binary is executable whether or not we move it: ZIP archives drop\n    // the exec bit, and the file may already carry the desired name.\n    if !file::is_executable(path) {\n        file::make_executable(path)?;\n    }\n    if path == target_path {\n        return Ok(());\n    }\n    if target_path.exists() {\n        bail!(\n            \"rename_exe: cannot rename '{}' to '{}': target already exists. \\\n             Check for duplicate or overlapping rename_exe mappings.\",\n            path.display(),\n            target_path.display()\n        );\n    }\n    file::rename(path, &target_path)?;\n    debug!(\"Renamed {} to {}\", path.display(), target_path.display());\n    Ok(())\n}\n\n/// Helper function to rename executable inside a macOS .app bundle\nfn rename_executable_in_app_bundle(\n    macos_dir: &Path,\n    target_path: &Path,\n    tool_name: Option<&str>,\n) -> eyre::Result<bool> {\n    // Find the first executable in the Contents/MacOS directory","sourceCodeStart":1151,"sourceCodeEnd":1187,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/backend/static_helpers.rs#L1151-L1187","documentation":"During install, mise applies `rename_exe` mappings by renaming a file inside the install dir; finish_rename refuses to overwrite an existing target. The collision means two mappings point at the same name, or the archive already contains a file with that name — silently dropping one would lose a binary, so the install fails loudly (src/backend/static_helpers.rs:1169).","triggerScenarios":"Two entries in a rename_exe map resolving to the same target name (e.g. both `tool-linux = \"tool\"` and `tool64 = \"tool\"` for one platform), or a rename target that already exists verbatim in the extracted archive, or an overlapping mapping where the source of one rename is the target of another.","commonSituations":"Copy-pasted rename_exe tables where the per-platform keys were changed but targets were not; archives that already ship a launcher with the generic name you renamed to; Windows extension handling (.exe) making two names collide after extension preservation.","solutions":["List your rename_exe mappings and make every target name unique, e.g. tool-linux -> \"tool-linux\" and tool-macos -> \"tool-macos\"","If the archive already contains a file named as the target, drop that mapping — no rename is needed","Check that one mapping's target is not another mapping's source (chained renames overlap)"],"exampleFix":"# before (mise.toml)\n[tools]\nmytool = { ..., rename_exe = { 'tool-linux' = 'tool', 'tool-linux-arm' = 'tool' } }\n\n# after\n[tools]\nmytool = { ..., rename_exe = { 'tool-linux' = 'tool-linux', 'tool-linux-arm' = 'tool-linux-arm' } }","handlingStrategy":"validation","validationCode":"# Bash/Rust-side preflight: reject duplicate rename targets\n# values: the rename_exe map from mise.toml\nfn unique_targets_ok(map: &std::collections::BTreeMap<String, String>) -> bool {\n    let mut seen = std::collections::BTreeSet::new();\n    map.values().all(|t| seen.insert(t.clone()))\n}\nassert!(unique_targets_ok(&[(\"a\".into(), \"x\".into()), (\"b\".into(), \"y\".into())].into_iter().collect()));\nassert!(!unique_targets_ok(&[(\"a\".into(), \"x\".into()), (\"b\".into(), \"x\".into())].into_iter().collect()));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Give each rename_exe mapping a distinct target name per platform","Don't rename to a name you know the archive already contains","Watch for extension-preserving collisions (.exe) on Windows"],"tags":["mise","rename-exe","install","file-collision","config-validation"],"backgroundTag":"file-already-exists","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}