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
- Nothing is broken: the previous installation was restored and works — investigate why the update failed (check network, disk space, permissions) and retry the update
- Check permissions on the install target directory (often /Applications or ~/Applications) and ensure the app bundle is not running/locked during update
- 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
- Close the running app before updating so target paths are not locked
- Check free disk space before starting an update
- Verify download integrity (checksum) before installing
- Run the installer with write permission to the target Applications directory
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
- A 'but' binary already exists at
- Could not remove quarantine attribute
- Failed to create symlink
- Failed to extract filename from download URL
- Failed to get app bundle name
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)