gitbutlerapp/gitbutler · warning
Could not remove quarantine attribute
Error message
Could not remove quarantine attribute: {e} - macOS may show security warnings What it means
On macOS the installer copies the staged .app to a temp location and runs remove_quarantine_recursive to strip the com.apple.quarantine xattr. If that fails, it warns with the error and notes macOS may show Gatekeeper security warnings, then continues the install and tells the user how to allow the app manually.
Solutions
- Continue with the install; when macOS blocks the app, open System Settings > Privacy & Security and click 'Allow Anyway' as the log suggests.
- Clear quarantine manually: xattr -dr com.apple.quarantine /Applications/<App>.app.
- Install onto the local APFS volume instead of a network mount.
- Run the installer from a normal terminal session with permission to modify extended attributes.
Defensive patterns
Strategy: fallback
Validate before calling
# Check quarantine status before/after install
import subprocess
def has_quarantine(path):
r = subprocess.run(['xattr', path], capture_output=True)
return b'com.apple.quarantine' in r.stdout Try / catch
// Warn-and-continue pattern
if let Err(e) = remove_quarantine_recursive(&install_app_new) {
warn("quarantine not removed: {e}; allow the app in System Settings > Privacy & Security");
} Prevention
- Run the installer from a local APFS volume, not a network mount
- Be ready to click 'Allow Anyway' in System Settings > Privacy & Security after first launch
- Prefer signed/notarized release artifacts so quarantine matters less
When it happens
Trigger: Raised in install_app (download_and_install_app) when remove_quarantine_recursive(&install_app_new) returns Err — typically xattr not available, the process lacks permission to change extended attributes, or the filesystem doesn't support xattrs (e.g. certain network/SMB volumes).
Common situations: Installing from a non-terminal context without permissions to run xattr; binaries not ad-hoc signed; installs onto SMB/NFS shares; hardened runtime environments; xattr command missing in minimal environments.
Related errors
- A 'but' binary already exists at
- Failed to create symlink
- Failed to extract filename from download URL
- Failed to get app bundle name
- Failed to move new installation into place - restoring…
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/7480042b359b653a.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-installer/src/install_macos.rs:104
.map(|c| format!(" channel {}", c.display_name()))
.unwrap_or_default(),
install_app.display()
));
// Clean up any leftover temp files from previous failed installations
let _ = fs::remove_dir_all(&install_app_new);
let _ = fs::remove_dir_all(&install_app_backup);
// Create Applications directory if it doesn't exist
fs::create_dir_all(home_dir.join("Applications"))?;
// Install to temporary location first
info("Installing to temporary location...");
copy_dir_all(app_dir, &install_app_new)?;
// Remove macOS quarantine attribute
if let Err(e) = remove_quarantine_recursive(&install_app_new) {
warn(&format!(
"Could not remove quarantine attribute: {e} - macOS may show security warnings"
));
info("If macOS blocks the app, go to System Settings > Privacy & Security and allow it");
}
// 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()View on GitHub (pinned to 58e5313667)