{"record":{"id":"a27d1d78b27f1bef","repo":"gitbutlerapp/gitbutler","slug":"failed-to-move-new-installation-into-place-e","errorCode":null,"errorMessage":"Failed to move new installation into place: {e}","messagePattern":"Failed to move new installation into place: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-installer/src/install_macos.rs","lineNumber":222,"sourceCode":"        cleanup_artifacts();\n\n        // Critical failure - restore backup if we created one\n        if had_backup && install_app_backup.exists() {\n            warn(\"Failed to move new installation into place - restoring backup\");\n            if let Err(restore_err) = fs::rename(&install_app_backup, &install_app) {\n                bail!(\n                    \"Failed to install new version: {}. Also failed to restore backup: {}. Your app may be at {}\",\n                    e,\n                    restore_err,\n                    install_app_backup.display()\n                );\n            }\n            bail!(\n                \"Failed to install new version: {e}. Previous installation restored successfully.\"\n            );\n        }\n        // No backup to restore, just fail\n        bail!(\"Failed to move new installation into place: {e}\");\n    }\n\n    // Update the symlink to point to the new installation\n    let final_target = install_app.join(\"Contents/MacOS/gitbutler-tauri\");\n    let _ = fs::remove_file(&but_symlink);\n\n    // Try to create symlink and verify - if either fails, rollback\n    let symlink_result = unix_fs::symlink(&final_target, &but_symlink);\n    let _ = fs::remove_file(&but_new);\n\n    if let Err(e) = symlink_result {\n        // Symlink creation failed - rollback to backup\n        warn(&format!(\n            \"Failed to create symlink: {e} - attempting to restore backup\"\n        ));\n        if install_app_backup.exists() {\n            if let Err(remove_err) = fs::remove_dir_all(&install_app) {\n                bail!(","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-installer/src/install_macos.rs#L204-L240","documentation":"The atomic swap rename of the new .app into place failed and there was no previous installation to restore (had_backup was false, i.e. no GitButler.app existed yet). The installer bails with just the underlying rename error, leaving the system without an installed app (stale artifacts were already cleaned up).","triggerScenarios":"install_app (via download_and_install_app) on a fresh machine (no existing install) when fs::rename(&install_app_new, &install_app) fails: destination volume read-only, permissions problem, disk full, or a non-empty directory already occupies the target path from a partially deleted install.","commonSituations":"First-ever CLI install on a locked-down corporate Mac; ~/Applications is not writable; leftover partial GitButler.app directory from a crashed previous install blocks the rename.","solutions":["Remove any partial directory at the install path (`rm -rf` the leftover GitButler.app) and retry","Check the destination is writable: `ls -ld` the install parent dir; fix ownership/permissions","Free disk space (`df -h`) if the disk is full","Ensure no process holds the destination path open, then rerun the installer"],"exampleFix":"// before: blindly retrying\ninstaller::download_and_install_app(...)?;\n// after: precheck target path is clear\nlet target = home.join(\"Applications/GitButler.app\");\nif target.exists() && !target.symlink_metadata()?.is_dir() {\n    bail!(\"unexpected file at {} - remove it before installing\", target.display());\n}","handlingStrategy":"validation","validationCode":"let target = home.join(\"Applications/GitButler.app\");\nif target.exists() {\n    bail!(\"stale path {} blocks install - remove it first\", target.display());\n}\nlet test = home.join(\"Applications/.write-test\");\nfs::write(&test, b\"x\").map_err(|e| format!(\"install dir not writable: {e}\"))?;\nlet _ = fs::remove_file(&test);","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"Failed to move new installation into place\") => {\n        eprintln!(\"check permissions/disk space at install path, then retry: {e}\");\n    }\n    other => other?,\n}","preventionTips":["Run installs as the owning user, never sudo","Delete partial installs from failed attempts before retrying","Check `df -h` free space on the target volume before updating"],"tags":["filesystem","installation","rename-failed","no-backup"],"backgroundTag":"file-write-failed","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}