gitbutlerapp/gitbutler · critical

Final installation verification failed

Error message

Final installation verification failed

What it means

After installing the Linux binary and setting 0o755 permissions, install_app validates the installed binary. If validate_installed_binary fails it warns 'Final installation verification failed' and attempts to restore the previous binary from backup. This catches installs that completed mechanically but produced a broken/non-runnable binary.

Solutions

  1. Read the following log lines: if a backup exists the installer restores it and tells you whether the restore succeeded.
  2. Re-download and re-run the installer; verify the archive checksum before installing.
  3. Run the installed binary directly (./but --version) to see the real loader error (e.g. 'cannot execute binary file', 'GLIBC_2.xx not found').
  4. Confirm the binary matches your architecture (uname -m) and OS; pick the correct release artifact.
  5. Ensure sufficient free disk space and re-extract.
Defensive patterns

Strategy: validation

Validate before calling

# Validate download before install
import hashlib, subprocess
def verify(archive, expected_sha256, arch):
    assert hashlib.sha256(open(archive,'rb').read()).hexdigest() == expected_sha256
    out = subprocess.run(['file', archive], capture_output=True).stdout.decode()
    assert arch in out, f'architecture mismatch: {out}'

Try / catch

// Validate after install; roll back on failure
if !validate_installed_binary(&install_bin_path) {
    if let Some(backup) = &but_backup {
        fs::rename(backup, &install_bin_path)?;
        bail!("installation failed; previous version restored");
    }
    bail!("installation failed validation and no backup exists");
}

Prevention

When it happens

Trigger: Raised in install_app (download_and_install_app) when validate_installed_binary(&install_bin_path) returns false after fs::set_permissions — e.g. truncated download, wrong architecture binary, corrupted extraction, or exec bit/interpreter problems.

Common situations: Corrupted or truncated download from a flaky network/mirror; glibc too old for the shipped binary; x86_64 binary installed on aarch64; partial extraction of an archive; disk-full during extraction.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


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

Appendix: 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 58e5313667)