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

  1. Re-run the CLI install action and complete the admin prompt to finish the install
  2. Or install manually: copy the but binary into the target bin directory with sudo
  3. Frontends: match Code::CliInstallCancelled via the error chain and show retry/manual instructions, not an error
  4. 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

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


AI-assisted analysis of gitbutlerapp/gitbutler@2497b8007a (2026-08-17). Data as JSON: /api/errors/9b049e44a41c887c. Report an issue: GitHub.