gitbutlerapp/gitbutler · error

Installation failed but your previous installation was…

Error message

Installation failed but your previous installation was restored

What it means

The macOS `but` CLI installer failed to install the newly downloaded .app bundle, but a backup of the previous installation existed, was restored, and passed binary validation. The installer reports the good news (previous install restored) and then aborts with this error so the caller knows the update did not succeed even though `but` remains usable.

Solutions

  1. Nothing is broken: the previous installation was restored and works — investigate why the update failed (check network, disk space, permissions) and retry the update
  2. Check permissions on the install target directory (often /Applications or ~/Applications) and ensure the app bundle is not running/locked during update
  3. Re-run the installer; if it repeatedly fails, download the release archive manually and replace the app bundle by hand

Example fix

// before: treating restore as a hard failure
bail!("Installation failed but your previous installation was restored");
// after: caller-side handling
match install_result {
    Err(e) if e.to_string().contains("previous installation was restored") => {
        warn!("Update failed; still running previous version. Will retry later.");
    }
    Err(e) => return Err(e),
    Ok(()) => {}
}
Defensive patterns

Strategy: fallback

Validate before calling

fn previous_install_ok(but_symlink: &std::path::Path) -> bool {
    but_symlink.exists() && std::fs::read_link(but_symlink).map(|t| t.exists()).unwrap_or(false)
}

Type guard

fn is_restored_error(e: &anyhow::Error) -> bool {
    e.to_string().contains("previous installation was restored")
}

Try / catch

match download_and_install_app(...).await {
    Err(e) if is_restored_error(&e) => warn!("update failed, previous version still active"),
    Err(e) => return Err(e),
    Ok(v) => Ok(v),
}

Prevention

When it happens

Trigger: install_app (via download_and_install_app) fails to move/replace the downloaded app into place, a backup directory exists and is copied back over the target, unix_fs::symlink re-points the `but` symlink at the restored binary, and validate_installed_binary(&but_symlink) succeeds — then bail! is called.

Common situations: Corrupted or partially downloaded update archive, target app bundle in use or write-protected so the install step fails, disk full during copy, upgrade attempts over an existing healthy installation where the backup path is populated.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/314308e432bae77b. Report an issue: GitHub.

Appendix: source

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

        } else {
            bail!("Failed to create symlink: {e}. No backup available to restore.");
        }
    }

    if !validate_installed_binary(&but_symlink) {
        // Try to restore backup
        warn("Final installation verification failed - attempting to restore backup");
        if install_app_backup.exists() {
            fs::remove_dir_all(&install_app)?;
            fs::rename(&install_app_backup, &install_app)?;

            let restored_target = install_app.join("Contents/MacOS/gitbutler-tauri");
            let _ = fs::remove_file(&but_symlink);
            unix_fs::symlink(&restored_target, &but_symlink)?;

            if validate_installed_binary(&but_symlink) {
                success("Backup was restored successfully");
                bail!("Installation failed but your previous installation was restored");
            } else {
                bail!(
                    "Installation failed and backup restoration also failed - 'but' command may not work"
                );
            }
        } else {
            bail!("Installation failed and no backup available to restore");
        }
    }

    success(&format!(
        "{} installed successfully",
        app_basename.to_string_lossy()
    ));
    // Remove backup on success
    let _ = fs::remove_dir_all(&install_app_backup);

    success("GitButler CLI (but) installed successfully");

View on GitHub (pinned to 58e5313667)