gitbutlerapp/gitbutler · warning

Found existing 'but' symlink pointing to: {existing_target_s

Error message

Found existing 'but' symlink pointing to: {existing_target_str}

What it means

Warning from the macOS installer when ~/.local/bin/but is a symlink whose target is neither a Nightly build (target string contains 'Nightly') nor a GitButler.app release (contains '/GitButler.app/'). The installer classifies it as a custom, non-GitButler symlink (previous_channel is None) and warns because the final swap step will overwrite it with a symlink to the new app bundle. It is purely informational; the install proceeds.

Source

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

        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") {
            Some(Channel::Nightly)
        } else if existing_target_str.contains("/GitButler.app/") {
            Some(Channel::Release)
        } else {
            None
        };

        if previous_channel.is_none() {
            warn(&format!(
                "Found existing 'but' symlink pointing to: {existing_target_str}"
            ));
            warn("This will be replaced with GitButler's 'but' command");
            info(
                "Note: Your custom symlink setup will be overwritten. The original target is not a GitButler installation.",
            );
        }
    }

    // Create temporary symlink to test the new installation
    let new_app_macos_dir = install_app_new.join("Contents/MacOS/gitbutler-tauri");
    let _ = fs::remove_file(&but_new);

    unix_fs::symlink(&new_app_macos_dir, &but_new)?;

    // Verify the new installation works
    let verify_status = Command::new(&but_new)
        .arg("--version")

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Note the target printed in the warning, then let the installer overwrite it; re-create your custom link afterwards if it pointed at something you still need (ln -sfn /your/target ~/.local/bin/but)
  2. Preempt the warning by removing the symlink before installing: rm ~/.local/bin/but
  3. If the target was a cargo-installed CLI you still want, keep it reachable via its original path (e.g. ~/.cargo/bin/but is already on PATH)
  4. Confirm after install: readlink ~/.local/bin/but should show .../GitButler.app/Contents/MacOS/gitbutler-tauri

Example fix

# before
readlink ~/.local/bin/but
/Users/me/.cargo/bin/but            # custom target, will be overwritten

# after install - restore your custom link under another name if needed
ln -sfn /Users/me/.cargo/bin/but ~/.local/bin/but-custom
Defensive patterns

Strategy: validation

Validate before calling

# Before installing, see what the symlink points at:
target=$(readlink ~/.local/bin/but 2>/dev/null)
if [ -n "$target" ] && ! [[ "$target" == *GitButler.app* ]] && ! [[ "$target" == *Nightly* ]]; then
  echo "custom symlink -> $target will be replaced by the installer"
  echo "$target" > ~/but-symlink.bak   # persist it yourself
fi

Prevention

When it happens

Trigger: Existing symlink created by the user, e.g. ln -s ~/.cargo/bin/but ~/.local/bin/but, a self-compiled build in ~/builds/but, or a symlink to an unrelated tool that also happens to be named 'but'. Channel detection at install_macos.rs:144-150 fails both the 'Nightly' and '/GitButler.app/' substring checks, so previous_channel is None and the warn fires at line 153.

Common situations: Dotfile-managed symlinks; switching from a source-build CLI to the desktop-app-installed one; tool name collision with another 'but' binary; stale symlink left behind after moving a self-built app.

Related errors


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