gitbutlerapp/gitbutler · error
Final installation verification failed
Error message
Final installation verification failed
What it means
The Linux installer copies the new but binary into place (fs::copy because /tmp is often tmpfs on a different mount, so rename would fail cross-device), sets mode 0o755, then validates the result by executing it. This warn fires when validation fails; with a backup present it renames the backup over the new binary and re-validates, bailing either 'restored' or 'restoration also failed'.
Source
Thrown at crates/but-installer/src/install_linux.rs:109
info(&format!(
"Installing{} to {}...",
channel
.map(|c| format!(" channel {}", c.display_name()))
.unwrap_or_default(),
install_bin_path.to_string_lossy(),
));
// NOTE: Must copy rather than rename. Rename assumes source and dest are on the same mount
// point, but /tmp on Linux systems is very often an in-memory file system (tmpfs) and thus on
// a different mount point than persistent files
fs::copy(but_path, &install_bin_path)?;
let mut perms = fs::metadata(&install_bin_path)?.permissions();
perms.set_mode(0o755);
fs::set_permissions(&install_bin_path, perms)?;
if !validate_installed_binary(&install_bin_path) {
warn("Final installation verification failed");
if let Some(but_backup) = but_backup {
warn("Attempting to restore backup");
fs::rename(&but_backup, &install_bin_path)?;
if validate_installed_binary(&install_bin_path) {
info("Backup restored successfully, exiting ...");
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");
}
} else if let Some(but_backup) = but_backup {
info(&format!(View on GitHub (pinned to caf1f223d3)
Solutions
- Check disk space and re-run the installer — truncated copies are the most common cause
- Verify the downloaded binary's architecture matches uname -m
- Confirm the install path is not mounted noexec (mount | grep home)
- If the bail says the backup was restored, retry later; if 'but' is broken with no backup, reinstall from the official installer
Defensive patterns
Strategy: fallback
Validate before calling
// Validate the artifact before touching the installed path
fn binary_runs(path: &std::path::Path) -> bool {
std::process::Command::new(path).arg("--version").output().is_ok()
}
// run on the staged or downloaded binary first Try / catch
if !validate_installed_binary(&install_bin_path) {
if let Some(but_backup) = but_backup {
fs::rename(&but_backup, &install_bin_path)?;
if !validate_installed_binary(&install_bin_path) {
bail!("restore failed — 'but' may not work");
}
bail!("Installation failed but your previous installation was restored");
}
bail!("Installation failed and no backup available to restore");
} Prevention
- Verify checksums of downloaded binaries before installing
- Check free disk space before fs::copy
- Match architecture and libc to the target machine
- Keep the backup until the new binary passes validation
When it happens
Trigger: validate_installed_binary(&install_bin_path) returns false at crates/but-installer/src/install_linux.rs:109 — the copied binary is truncated or corrupt (disk filled during the copy), built for the wrong architecture or libc, or cannot execute (permissions, noexec mount).
Common situations: Disk filling mid-copy; an arm64 binary on x86_64 or vice versa; home directory mounted noexec; glibc older than the binary requires.
Related errors
- Failed to determine home directory
- Failed to move new installation into place - restoring backu
- Attempting to restore backup
- When using OpenAI in a bring your own key configuration, you
- BUG: we do not create or work with symlinks
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/7d88bc9ec37ad83b.
Report an issue: GitHub.