gitbutlerapp/gitbutler · error
Failed to move new installation into place - restoring backu
Error message
Failed to move new installation into place - restoring backup
What it means
The macOS updater stages a new app bundle (install_app_new), optionally backs up the current one, then fs::rename()s the staged bundle over the real location in ~/Applications. If that rename fails, this warn announces rollback: artifacts are cleaned and the backup is renamed back into place. Failure of both renames bails with a combined message naming where the old app was left.
Source
Thrown at crates/but-installer/src/install_macos.rs:208
let _ = fs::remove_file(&but_new);
};
// Backup existing installation if it exists
let had_backup = install_app.exists();
if had_backup && let Err(e) = fs::rename(&install_app, &install_app_backup) {
// Failed to backup - clean up artifacts before failing
cleanup_artifacts();
return Err(e.into());
}
// Move new installation into place with rollback on failure
if let Err(e) = fs::rename(&install_app_new, &install_app) {
// Clean up stale artifacts before handling the error
cleanup_artifacts();
// Critical failure - restore backup if we created one
if had_backup && install_app_backup.exists() {
warn("Failed to move new installation into place - restoring backup");
if let Err(restore_err) = fs::rename(&install_app_backup, &install_app) {
bail!(
"Failed to install new version: {}. Also failed to restore backup: {}. Your app may be at {}",
e,
restore_err,
install_app_backup.display()
);
}
bail!(
"Failed to install new version: {e}. Previous installation restored successfully."
);
}
// No backup to restore, just fail
bail!("Failed to move new installation into place: {e}");
}
// Update the symlink to point to the new installation
let final_target = install_app.join("Contents/MacOS/gitbutler-tauri");View on GitHub (pinned to caf1f223d3)
Solutions
- Fix permissions or ownership of the Applications folder (or reinstall under the user's ~/Applications) and re-run the installer
- Free disk space, then update again
- If the bail names a backup path, manually move that app back into place
- If both renames failed and no app remains, download and install fresh
Defensive patterns
Strategy: fallback
Validate before calling
fn dir_is_writable(dir: &std::path::Path) -> bool {
let probe = dir.join(".but-write-probe");
std::fs::write(&probe, b"1").is_ok() && std::fs::remove_file(&probe).is_ok()
}
// call before staging: dir_is_writable(&home_dir.join("Applications")) Try / catch
if let Err(e) = fs::rename(&install_app_new, &install_app) {
cleanup_artifacts();
if let Err(restore_err) = fs::rename(&install_app_backup, &install_app) {
bail!("install failed: {e}; restore failed: {restore_err}; old app at {}",
install_app_backup.display());
}
bail!("Installation failed: {e}. Previous installation restored.");
} Prevention
- Verify the destination directory is writable before staging a new bundle
- Keep old and new bundles on the same volume
- Quit the running app before updating
- Delete the backup only after the final rename is verified
When it happens
Trigger: fs::rename(&install_app_new, &install_app) fails at crates/but-installer/src/install_macos.rs:208 — ~/Applications not writable by the user, disk full, backup or staged bundle on a different volume, or another process holding a lock on the bundle.
Common situations: Applications directory owned by another admin account; disk-full machines; the app moved across volumes before updating; security software locking .app bundles during updates.
Related errors
- Failed to create symlink: {e} - attempting to restore backup
- Failed to install new version: {}. Also failed to restore ba
- Failed to install new version: {e}. Previous installation re
- Failed to move new installation into place: {e}
- Final installation verification failed
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/2770059f00144b18.
Report an issue: GitHub.