gitbutlerapp/gitbutler · error
Failed to resolve bin dir path
Error message
Failed to resolve bin dir path
What it means
install_app computes the user's binary install path via but_binary_path(home_dir) and then calls .parent() to obtain the bin directory to create. If the computed path has no parent (e.g. the path is a bare root/empty component), it throws "Failed to resolve bin dir path". This is an internal invariant violation: but_binary_path normally returns a nested path like <home>/bin/but, which always has a parent.
Solutions
- Check that the installer's home_dir / HOME is set to a normal absolute user home path (e.g. /home/alice), not "/" or empty
- Re-run the installer without custom home-dir overrides
- If it persists, inspect but_binary_path in but-installer to confirm it appends a subdirectory (bin) to home_dir
Example fix
// before
let bin_dir = install_bin_path.parent().ok_or_else(|| anyhow!("Failed to resolve bin dir path"))?;
// after
let bin_dir = install_bin_path.parent().unwrap_or_else(|| Path::new(home_dir)); // fall back to home dir Defensive patterns
Strategy: validation
Validate before calling
let install_bin_path = but_binary_path(&home_dir);
if install_bin_path.parent().is_none() {
return Err("home_dir does not yield a nested bin path".into());
} Prevention
- Always pass an absolute, non-root home directory to the installer
- Assert home_dir is not "/" or empty before install
- Add a unit test for but_binary_path with edge-case home dirs
When it happens
Trigger: install_app is invoked with a home_dir for which but_binary_path returns a path without a parent component — practically only when the path resolution degenerates to a root or empty path.
Common situations: Running the installer with a misconfigured or empty home directory override (e.g. home_dir set to "/" or an empty string), or future changes to but_binary_path that return a non-nested path.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Attempting to restore backup
- Failed to construct but cli URL
- Failed to get app bundle name
- Failed to get signature for but, requested version may be…
- Final installation verification failed
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/bf600211671d16df.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-installer/src/install_linux.rs:67
download_file(&download_url, &tmp_filepath)?;
info("Download completed successfully");
let signature_b64 = download_to_string(&signature_url).with_context(|| {
anyhow!("Failed to get signature for but, requested version may be too old")
})?;
verify_signature(&tmp_filepath, &signature_b64, temp_dir.path())?;
// Install the app bundle
install_app(&tmp_filepath, &config.home_dir, channel)?;
Ok(())
}
fn install_app(but_path: &Path, home_dir: &Path, channel: Option<Channel>) -> Result<()> {
let install_bin_path = but_binary_path(home_dir);
let bin_dir = install_bin_path
.parent()
.ok_or_else(|| anyhow!("Failed to resolve bin dir path"))?;
fs::create_dir_all(bin_dir)?;
let but_backup = if install_bin_path.is_file() {
let suffix: u64 = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_nanos() as u64 ^ std::process::id() as u64)
.unwrap_or(std::process::id() as u64);
let mut backup_name = install_bin_path.as_os_str().to_owned();
backup_name.push(format!(".{suffix:x}"));
let but_backup = std::path::PathBuf::from(backup_name);
info(&format!(
"Found existing install at {}, backing up to {}",
install_bin_path.to_string_lossy(),
but_backup.to_string_lossy()
));
fs::rename(&install_bin_path, &but_backup)?;View on GitHub (pinned to 58e5313667)