gitbutlerapp/gitbutler · warning

A 'but' binary already exists at {} (not a symlink)

Error message

A 'but' binary already exists at {} (not a symlink)

What it means

The macOS installer manages ~/.local/bin/but as a symlink to the app's bundled CLI. When a regular file already sits at that path (a user's own script or a manually copied binary), the installer warns, renames the existing file to but.backup.<unix-timestamp> to preserve it, and continues creating its symlink. Nothing of the user's is deleted, but their `but` command now resolves to GitButler's CLI.

Source

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

    }

    // Create bin directory
    let bin_dir = home_dir.join(".local/bin");
    fs::create_dir_all(&bin_dir)?;

    // Check for existing 'but' and detect channel switching
    let but_symlink = bin_dir.join("but");
    let but_new = bin_dir.join("but.new");

    if but_symlink.exists() && !but_symlink.is_symlink() {
        // 'but' exists but is not a symlink
        let now = std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .unwrap_or_default()
            .as_secs();
        let timestamp = format!("{now}");
        let but_backup = bin_dir.join(format!("but.backup.{timestamp}"));
        warn(&format!(
            "A 'but' binary already exists at {} (not a symlink)",
            but_symlink.display()
        ));
        warn(&format!(
            "Moving it to {} to preserve your existing file",
            but_backup.display()
        ));
        fs::rename(&but_symlink, &but_backup)?;
        info(&format!(
            "Your original 'but' has been saved to: {}",
            but_backup.display()
        ));
    } else if but_symlink.is_symlink() {
        let existing_target = fs::read_link(&but_symlink)?;
        let existing_target_str = existing_target.to_string_lossy();

        // Detect channel switching
        let previous_channel = if existing_target_str.contains("Nightly") {

View on GitHub (pinned to caf1f223d3)

Solutions

  1. If you had a custom binary or script, recover it from ~/.local/bin/but.backup.<timestamp> and rename it back or elsewhere on PATH
  2. To adopt the official CLI wholesale, remove leftover but.backup.* files
  3. Verify afterwards: ls -l ~/.local/bin/but should show a symlink into the app bundle
  4. Expect the warning again on future updates only if a new non-symlink file reappears at the path
Defensive patterns

Strategy: validation

Validate before calling

let but_symlink = bin_dir.join("but");
if but_symlink.exists() && !but_symlink.is_symlink() {
    // decide before installing: back it up yourself, or let the installer rename it
}

Prevention

When it happens

Trigger: ~/.local/bin/but exists and is not a symlink when the installer runs (crates/but-installer/src/install_macos.rs:126) — the user previously copied a binary there, another tool wrote a real-file shim, or an old manual install left a file behind.

Common situations: Custom `but` scripts from other tooling; PATH managers writing real-file shims; users who followed older manual CLI install docs.

Related errors


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