gitbutlerapp/gitbutler · error
Unexpected CLI installer response
Error message
Unexpected CLI installer response
What it means
After a successful exit status, check_cli_install_output requires the installer script's stdout to be exactly the sentinel 'gitbutler-cli-installed' (or the known cancellation sentinel). Any other stdout — even with exit code 0 — means the script's contract is broken, so this internal-invariant error is thrown to catch corrupted installs, wrapper interference, or script/API drift between app versions.
Solutions
- Reinstall the GitButler app so the bundled install script matches the code that validates it (version alignment).
- Run the install without output-wrapping shells/aliases that could add text to stdout.
- If developing, confirm the script's success path still returns exactly 'gitbutler-cli-installed' and the cancellation path 'gitbutler-cli-install-cancelled'.
Example fix
// before: script edited to return 'ok' return "ok" -- -> ensure! fails: Unexpected CLI installer response // after return "gitbutler-cli-installed"
Defensive patterns
Strategy: try-catch
Try / catch
if let Err(e) = install_cli_link_escalated(...) {
if format!("{e:#}").contains("Unexpected CLI installer response") {
// app/script version mismatch: reinstall the app so the bundled script matches
}
} Prevention
- Keep the app and its bundled install script version-aligned; never hand-edit the AppleScript.
- Run installs without stdout-redirecting wrappers or shell profile noise.
- Preserve the exact success/cancellation sentinels when modifying the installer.
When it happens
Trigger: install_cli_link_escalated's AppleScript exits 0 but stdout is neither 'gitbutler-cli-installed\n' nor 'gitbutler-cli-install-cancelled\n' — e.g. the script was modified, its output was prefixed by shell profile noise, or an older/newer script version prints a different sentinel.
Common situations: Mismatched app/CLI versions where the bundled AppleScript was changed; output piping/logging wrappers injecting text into stdout; tampered or corrupted app resources.
Related errors
- CLI installation failed
- CliInstallCancelled
- Refusing to replace ' ', which points to ' ' instead of
- A 'but' binary already exists at
- An octopus merge commits must have at least two parents
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/314fb4c46b6b257a.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-action/src/cli.rs:239
"#;
#[cfg(any(target_os = "macos", all(test, unix)))]
fn check_cli_install_output(output: std::process::Output) -> anyhow::Result<()> {
anyhow::ensure!(
output.status.success(),
"CLI installation failed ({}): {}",
output.status,
String::from_utf8_lossy(&output.stderr).trim()
);
if output.stdout == b"gitbutler-cli-install-cancelled\n" {
return Err(
anyhow!("Administrator authorization was cancelled").context(ErrorContext::new_static(
Code::CliInstallCancelled,
"CLI install cancelled",
)),
);
}
anyhow::ensure!(
output.stdout == b"gitbutler-cli-installed\n",
"Unexpected CLI installer response"
);
Ok(())
}
#[cfg(target_os = "macos")]
pub fn auto_fix_broken_but_cli_symlink() {
let Ok(absolute_link_destination) = std::fs::read_link(UNIX_LINK_PATH) else {
return;
};
if absolute_link_destination.exists() {
return;
}
let result = get_cli_path().and_then(|source| {
do_install_cli_v2(
&source,View on GitHub (pinned to 58e5313667)