gitbutlerapp/gitbutler · info · ErrorContext
CliInstallCancelled
CliInstallCancelled
Error message
CLI install cancelled
What it means
Constructed in crates/but-action/src/cli.rs:85 when the macOS osascript-based CLI installer (copying the but binary into place with admin privileges) exits with status 1 — the user dismissed the admin-privileges prompt. It is intentionally benign and tagged with the but_error Code::CliInstallCancelled so frontends classify by code (via the anyhow error chain) instead of matching the English message; the desktop app shows a neutral info toast rather than an error.
Source
Thrown at crates/but-action/src/cli.rs:85
ln -sf \'{}\' \'{UNIX_LINK_PATH}\' \
\" with administrator privileges",
cli_path.display()
),
])
.stdout(std::process::Stdio::inherit())
.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 {View on GitHub (pinned to 2497b8007a)
Solutions
- Re-run the CLI install action and complete the admin prompt to finish the install
- Or install manually: copy the but binary into the target bin directory with sudo
- Frontends: match Code::CliInstallCancelled via the error chain and show retry/manual instructions, not an error
- If the prompt never appears, check that /usr/bin/osascript is permitted by management profiles
Example fix
// before
Err(anyhow!("osascript exited with status 1").context(ErrorContext::new_static(
Code::CliInstallCancelled,
"CLI install cancelled",
)))
// after — a caller classifying by code instead of the message
use but_error::{AnyhowContextExt, Code};
if let Some(ctx) = err.custom_context() {
if ctx.code == Code::CliInstallCancelled {
return Outcome::Cancelled; // benign: show info toast, offer retry
}
} Defensive patterns
Strategy: fallback
Try / catch
use but_error::{AnyhowContextExt, Code};
match install_cli() {
Err(e) if e.custom_context().is_some_and(|c| c.code == Code::CliInstallCancelled) => {
// benign: the user dismissed the macOS admin prompt — offer retry or manual install
show_info_toast("CLI install cancelled", ["Retry", "Show manual steps"]);
}
res => res?,
} Prevention
- Classify by but_error Code via the error chain, never by matching the message string
- Treat CliInstallCancelled as info with a retry affordance, not an error
- Always offer a documented manual install path as the fallback
- Check device-policy permissions for osascript on managed Macs when installs silently cancel
When it happens
Trigger: Running the CLI install action on macOS and clicking Cancel on the admin privileges dialog; the osascript prompt interrupted or dismissed before credentials are entered.
Common situations: Users aborting the sudo/admin prompt; prompt fatigue when the dialog appears twice; managed Macs where the privileges dialog is blocked by device policy.
Related errors
- osascript exited with status {}
- Failed to persist action: {e}
- Failed to list actions: {e}
- Would probably need to run "ln -sf '{}' '{UNIX_LINK_PATH}'"{
- DefaultTerminalNotFound
AI-assisted analysis of gitbutlerapp/gitbutler@2497b8007a (2026-08-17).
Data as JSON: /api/errors/9b049e44a41c887c.
Report an issue: GitHub.