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

  1. Create the symlink manually with the command the installer prints: sudo ln -sf '<but-binary-path>' /usr/local/bin/but
  2. Verify /usr/local/bin exists and is writable by an admin
  3. If MDM blocks elevation, install into a user-writable PATH directory (~/bin, /opt/homebrew/bin) and symlink there instead
  4. 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

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


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)