gitbutlerapp/gitbutler · error

Failed to create symlink: {e}. No backup available to restor

Error message

Failed to create symlink: {e}. No backup available to restore.

What it means

First macOS install: creating the 'but' symlink failed and no backup exists to restore. The new app may be installed, but the CLI link is missing. Same failure class as the restored variant - the link path is unwritable or occupied - except there is nothing to fall back to.

Source

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

            "Failed to create symlink: {e} - attempting to restore backup"
        ));
        if install_app_backup.exists() {
            if let Err(remove_err) = fs::remove_dir_all(&install_app) {
                bail!(
                    "Failed to create symlink and failed to remove new installation during rollback: {}. Backup at: {}",
                    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 {

View on GitHub (pinned to caf1f223d3)

Solutions

  1. mkdir -p ~/.local/bin and ensure it is user-writable, then re-run the installer
  2. Or create the link manually: ln -s /Applications/GitButler.app/Contents/MacOS/gitbutler-tauri ~/.local/bin/but
  3. Remove any directory occupying the but path first
  4. Verify ~/.local/bin is on PATH afterwards

Example fix

# manual completion of a first install that failed here
mkdir -p ~/.local/bin
ln -s /Applications/GitButler.app/Contents/MacOS/gitbutler-tauri ~/.local/bin/but
Defensive patterns

Strategy: validation

Validate before calling

// Pre-create and probe the symlink dir before a first install
let bin_dir = home.join(".local/bin");
std::fs::create_dir_all(&bin_dir)?; // fails clearly if HOME is not writable
let probe = bin_dir.join(".write-probe");
std::fs::write(&probe, b"")?;
std::fs::remove_file(&probe)?;
anyhow::ensure!(!bin_dir.join("but").is_dir(), "a directory occupies the 'but' path");

Try / catch

if let Err(e) = but_installer::run_installation_with_version(request, false) {
    let msg = e.to_string();
    if msg.contains("Failed to create symlink") && msg.contains("No backup available") {
        // complete the first install by hand
        let _ = std::fs::remove_file(home.join(".local/bin/but"));
        std::os::unix::fs::symlink(
            install_app.join("Contents/MacOS/gitbutler-tauri"),
            home.join(".local/bin/but"))?;
    }
    return Err(e);
}

Prevention

When it happens

Trigger: unix_fs::symlink fails because ~/.local/bin cannot be created or written (parent not writable, read-only home), a non-file object already occupies the but path, or the link target directory is missing.

Common situations: Fresh machines with corporate read-only or root-owned home mounts; stray 'but' directory; PATH bin dir never created.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/ceee142d9a7ee34b. Report an issue: GitHub.