gitbutlerapp/gitbutler · error
osascript exited with status
Error message
osascript exited with status {} What it means
Returned by the macOS CLI installer when the osascript privilege-elevation script exits with any status other than 0 or 1. Unlike status 1 (user cancel), other codes mean the privileged shell script itself failed: symlink target missing, /usr/local/bin absent, policy blocking elevation, or osascript errors. The message includes the numeric status, or 'unknown' when the process was terminated by a signal.
Solutions
- Create the symlink manually with the command the installer prints: sudo ln -sf '<but-binary-path>' /usr/local/bin/but
- Verify /usr/local/bin exists and is writable by an admin
- If MDM blocks elevation, install into a user-writable PATH directory (~/bin, /opt/homebrew/bin) and symlink there instead
- Fix the environment, then retry the in-app install
Example fix
# before: osascript exited with status 2 (privileged ln failed) # after: perform the link manually sudo mkdir -p /usr/local/bin sudo ln -sf "$APP_CLI_PATH" /usr/local/bin/but but --version
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight the target dir before triggering elevation
let ok = std::fs::symlink_metadata("/usr/local/bin")
.map(|m| m.is_dir())
.unwrap_or(false);
if !ok {
// install into a user PATH dir instead of elevating
} Try / catch
match do_install_cli(mode) {
Err(e) if e.to_string().starts_with("osascript exited with status") => {
// fall back to printing or running the manual `ln -sf` instruction
}
r => r,
} Prevention
- Pre-create /usr/local/bin or choose a user-writable install dir
- Account for MDM privilege policy on managed fleets
- Install the app/binary in a stable location before linking
When it happens
Trigger: do_install_cli on macOS with AllowPrivilegeElevation: osascript runs but the privileged 'ln -sf' fails - /usr/local/bin does not exist, the cli path is on a volume the privileged shell cannot resolve, or MDM profiles deny administrator privileges - yielding a non-0/1 exit code.
Common situations: Corporate Macs with MDM privilege restrictions; /usr/local/bin removed or not writable; the app run from a transient location (disk image) whose cli path is unstable; broken shell environments.
Related errors
- A 'but' binary already exists at
- Failed to create symlink
- Found existing 'but' symlink pointing to
- Moving it to to preserve your existing file
- osascript directory picker failed
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/680b930637d1f9cb.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-action/src/cli.rs:91
.stderr(std::process::Stdio::inherit())
.status()
.context("Failed to run osascript")?;
if status.success() {
Ok(())
} else if status.code() == Some(1) {
// osascript exits 1 when the user dismisses the admin-privileges
// prompt. This is a benign abort, not an error — tag it with a
// dedicated Code so the frontend can react based on the code
// rather than matching on an English message.
Err(
anyhow!("osascript exited with status 1").context(ErrorContext::new_static(
Code::CliInstallCancelled,
"CLI install cancelled",
)),
)
} else {
Err(anyhow!(
"osascript exited with status {}",
status
.code()
.map(|c| c.to_string())
.unwrap_or_else(|| "unknown".into())
))
}
} else {
Err(anyhow!(
"Would probably need to run \"ln -sf '{}' '{UNIX_LINK_PATH}'\"{privilege}",
cli_path.display(),
privilege = if can_elevate_privileges {
" with root permissions"
} else {
""
}
))
}View on GitHub (pinned to caf1f223d3)