gitbutlerapp/gitbutler · critical

Failed to install new version: {}. Also failed to restore ba

Error message

Failed to install new version: {}. Also failed to restore backup: {}. Your app may be at {}

What it means

Critical macOS rollback failure: fs::rename of the staged new .app into the install location failed, and the follow-up rename restoring the backup failed too. The message embeds the original rename error, the restore error, and the backup path where the previous app still sits. The install location may now be empty or partial, so manual recovery is expected.

Source

Thrown at crates/but-installer/src/install_macos.rs:210

    // 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");
    let _ = fs::remove_file(&but_symlink);

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Quit GitButler completely (Cmd-Q) and retry the install
  2. Manually restore from the printed backup path: mv '<backup path from the message>' /Applications/GitButler.app
  3. Free disk space and fix permissions on the install dir, then rerun but-installer
  4. If the backup path no longer exists, do a fresh install and treat the previous app as lost

Example fix

# recovery for the state after this error
mv "$(path printed after 'Your app may be at')" /Applications/GitButler.app
ln -sf /Applications/GitButler.app/Contents/MacOS/gitbutler-tauri ~/.local/bin/but
Defensive patterns

Strategy: try-catch

Validate before calling

// Before an update: the app must not be running, and space must be available
let running = std::process::Command::new("pgrep")
    .arg("-x").arg("gitbutler-tauri")
    .stdout(std::process::Stdio::null())
    .status().is_ok_and(|s| s.success());
anyhow::ensure!(!running, "GitButler is running; quit it before updating");

Try / catch

if let Err(e) = but_installer::run_installation_with_version(request, false) {
    let msg = e.to_string();
    if msg.contains("Also failed to restore backup") {
        // recover manually from the path printed after "Your app may be at"
        let backup = msg.rsplit("Your app may be at ").next().unwrap_or_default();
        recover_app_from_backup(std::path::Path::new(backup.trim()))?;
    }
    return Err(e);
}

Prevention

When it happens

Trigger: The swap rename fails because the target app bundle is running (macOS locks bundle executables), the install dir is not writable, or the disk is full - and the backup restore then fails for the same or a compounding reason (permissions, disk full, SIP-protected path).

Common situations: Updating while GitButler desktop app is open; non-admin user installing into /Applications; disk pressure during the double-size swap window.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/8994d9e55d4c6bf5. Report an issue: GitHub.