gitbutlerapp/gitbutler · error
Final installation verification failed - attempting to…
Error message
Final installation verification failed - attempting to restore backup
What it means
After the symlink is created, install_app calls validate_installed_binary(&but_symlink) to confirm the installed binary actually runs. If validation fails, the installer warns and rolls back: it removes the new install dir, renames the backup back into place, and re-points (or removes) the symlink. This guards against shipping a broken binary that would leave the user with a non-functional 'but' command.
Solutions
- Re-download and re-run the installer to replace a possibly corrupted artifact.
- Clear the quarantine attribute (`xattr -dr com.apple.quarantine /Applications/GitButler.app`) and retry if Gatekeeper blocked execution.
- Verify you downloaded the artifact matching your CPU architecture (arm64 vs x86_64) or install Rosetta 2.
- Check Console.app / security logs for what killed the binary during validation, then address (codesign, AV exclusion).
Defensive patterns
Strategy: retry
Validate before calling
# Validate the artifact before install: run the binary directly. /usr/sbin/file '/Applications/GitButler.app/Contents/MacOS/gitbutler-tauri' xattr -l /Applications/GitButler.app | grep -i quarantine
Try / catch
const res = spawnSync(installer, { stdio: 'inherit' });
if (res.status !== 0 && fs.existsSync('/Applications/GitButler.app')) {
spawnSync('xattr', ['-dr', 'com.apple.quarantine', '/Applications/GitButler.app']);
// retry the install once
} Prevention
- Download installers over stable network connections; re-download if checksum differs.
- Match the artifact to your architecture (arm64 vs x86_64) and install Rosetta if needed.
- Pre-approve/notarize binaries in corporate environments that block unsigned executables.
- Exclude the install directory from antivirus quarantine heuristics.
When it happens
Trigger: download_and_install_app -> install_app on macOS when the freshly installed binary at but_symlink fails validate_installed_binary - e.g. the downloaded .app is corrupted, the binary lacks the executable bit, is unsigned/quarantined and fails to spawn, or the architecture does not match (x86_64 binary on arm64 without Rosetta).
Common situations: Interrupted/partial download producing a corrupt .app; Gatekeeper blocking an unnotarized binary so the spawn check fails; wrong-architecture artifact; antivirus quarantining gitbutler-tauri.
Related errors
- Failed to create symlink
- Final installation verification failed
- A 'but' binary already exists at
- Attempting to restore backup
- Could not remove quarantine attribute
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/3aa4533e3425d943.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-installer/src/install_macos.rs:260
remove_err,
install_app_backup.display()
);
}
fs::rename(&install_app_backup, &install_app)?;
let restored_target = install_app.join("Contents/MacOS/gitbutler-tauri");
let _ = fs::remove_file(&but_symlink);
let _ = unix_fs::symlink(&restored_target, &but_symlink);
bail!("Failed to create symlink: {e}. Previous installation was restored.");
} 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");View on GitHub (pinned to 58e5313667)