{"record":{"id":"591fc85aa32dbe13","repo":"gitbutlerapp/gitbutler","slug":"failed-to-install-new-version-e-previous-insta","errorCode":null,"errorMessage":"Failed to install new version: {e}. Previous installation restored successfully.","messagePattern":"Failed to install new version: (.+?)\\. Previous installation restored successfully\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-installer/src/install_macos.rs","lineNumber":217,"sourceCode":"    }\n\n    // Move new installation into place with rollback on failure\n    if let Err(e) = fs::rename(&install_app_new, &install_app) {\n        // Clean up stale artifacts before handling the error\n        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!(","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-installer/src/install_macos.rs#L199-L235","documentation":"The rename moving the new .app into the install location failed, but a backup existed and was restored successfully - the previous GitButler version is back in place. The original fs::rename error is embedded in the message, so the underlying cause (busy target, permissions, disk full) is still visible. This is the benign twin of the both-renames-failed critical branch.","triggerScenarios":"fs::rename of the staged app fails with EBUSY (app running), EACCES (install dir not writable), or ENOSPC (disk full); the backup rename back then succeeds because the cause was transient or specific to the staged path.","commonSituations":"Updating with the desktop app open; non-admin /Applications; temporary disk pressure that eased between the two renames.","solutions":["Read the embedded cause: 'Resource busy' - quit GitButler and retry; 'Permission denied' - fix ownership of the install dir; ENOSPC - free space","Re-run the installer once the cause is addressed; the old version keeps working meanwhile","df -h the install volume to rule out disk full"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// Pre-check the two usual rename blockers: running app and free space\nlet running = app_process_running()?; // pgrep gitbutler-tauri\nanyhow::ensure!(!running, \"quit GitButler before updating\");\nanyhow::ensure!(free_bytes(&install_dir)? > 2 * bundle_size, \"not enough disk space to swap\");","typeGuard":null,"tryCatchPattern":"match but_installer::run_installation_with_version(request, false) {\n    Err(e) if e.to_string().contains(\"Previous installation restored successfully\") => {\n        // old version is live again; safe to retry after the user quits the app\n        log::info!(\"update rolled back; retry after quitting GitButler\");\n    }\n    result => result,\n}","preventionTips":["Quit the desktop app before CLI-driven updates","Check free disk space on the install volume before updating","Read the embedded rename error to fix the real blocker before retrying"],"tags":["rust","macos","rollback-restored","rename","but-installer"],"backgroundTag":"installation-rollback","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}