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
- If you had a custom binary or script, recover it from ~/.local/bin/but.backup.<timestamp> and rename it back or elsewhere on PATH
- To adopt the official CLI wholesale, remove leftover but.backup.* files
- Verify afterwards: ls -l ~/.local/bin/but should show a symlink into the app bundle
- 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
- Install the CLI via the app so it owns the ~/.local/bin/but symlink
- Never park custom binaries at that exact path
- After updates, check but.backup.* files to recover anything you owned
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
- Refusing to install symlink onto existing non-symlink at '{U
- Moving it to {} to preserve your existing file
- Found existing 'but' symlink pointing to: {existing_target_s
- This will be replaced with GitButler's 'but' command
- Too many arguments. Usage: but-installer [version|nightly] o
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/3ac7058d1d7ba5a7.
Report an issue: GitHub.