{"record":{"id":"467800e1e0e2859a","repo":"jdx/mise","slug":"refusing-to-overwrite-non-empty-directory-pass","errorCode":null,"errorMessage":"refusing to overwrite non-empty directory {}; pass {} or choose an empty/new path","messagePattern":"refusing to overwrite non-empty directory (.+?); pass (.+?) or choose an empty/new path","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/install_into.rs","lineNumber":152,"sourceCode":"        // already exists at the install path. Check immediately before the\n        // install performs that deletion (rather than at the start of `run`) so\n        // a directory that became non-empty during tool resolution can't be\n        // clobbered without an explicit opt-in. Refuse to overwrite a non-empty\n        // directory (e.g. `.`) unless the user passes -y/--yes or confirms\n        // interactively; the prompt defaults to \"no\" since it is destructive.\n        // (#8115)\n        if path_has_contents(&install_path) {\n            let proceed = Settings::get().yes\n                || prompt::confirm_with_default(\n                    format!(\n                        \"{} is not empty; install-into will delete its contents. Continue?\",\n                        display_path(&install_path)\n                    ),\n                    false,\n                )?\n                .is_yes();\n            if !proceed {\n                bail!(\n                    \"refusing to overwrite non-empty directory {}; pass {} or choose an empty/new path\",\n                    display_path(&install_path),\n                    style(\"--yes\").yellow().for_stderr()\n                );\n            }\n        }\n        backend.install_version(install_ctx, tv).await?;\n        Ok(())\n    }\n}\n\n/// Replacement deletes the destination, so one that overlaps the lock directory\n/// in either direction is refused: an ancestor would take the whole directory\n/// with it, and a descendant could unlink an active lock file, letting the next\n/// process create a replacement and install alongside the holder.\nfn lock_dir_overlap(destination: &Path, lock_dir: &Path) -> eyre::Report {\n    eyre!(\n        \"install-into destination {} overlaps mise's lock directory {}; choose a different destination\",","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/cli/install_into.rs#L134-L170","documentation":"`mise install <tool>@<version> <path>` (install_into) refuses to install into a non-empty directory by default, to avoid clobbering existing files. The user is prompted to confirm; without a TTY/confirmation (or if they decline) mise bails, suggesting --yes to proceed.","triggerScenarios":"Running `mise install <tool>@<version> <existing-dir>` where the target install_path already contains files and neither an affirmative interactive confirmation nor the --yes flag is provided.","commonSituations":"Re-running an install into a previously populated directory; scripting/CI where there is no TTY so the prompt cannot be answered; re-using an old version directory by mistake.","solutions":["Pass --yes if you intentionally want to overwrite the non-empty directory.","Choose an empty or new target directory for the install.","Delete or clear the existing directory contents first if they are no longer needed.","In CI, decide explicitly: either pre-clean the directory or add --yes to the command."],"exampleFix":"// before (fails on non-empty dir, non-interactive)\nmise install node@20.0.0 ~/.nodes/20.0.0\n// after\nmise install --yes node@20.0.0 ~/.nodes/20.0.0","handlingStrategy":"validation","validationCode":"# shell: ensure target dir is empty (or absent) before non-interactive install\nif [ -d \"$DIR\" ] && [ -n \"$(ls -A \"$DIR\")\" ]; then echo \"refusing: $DIR not empty\"; exit 1; fi\nmise install node@20.0.0 \"$DIR\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pre-clean or choose a fresh directory before installing into an explicit path.","In CI/non-interactive contexts, always pass --yes deliberately or pre-validate emptiness.","Never reuse old version directories for new installs."],"tags":["cli","install","safety-guard","overwrite-protection"],"backgroundTag":"invalid-argument-value","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}