{"record":{"id":"680b930637d1f9cb","repo":"gitbutlerapp/gitbutler","slug":"osascript-exited-with-status","errorCode":null,"errorMessage":"osascript exited with status {}","messagePattern":"osascript exited with status (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-action/src/cli.rs","lineNumber":91,"sourceCode":"            .stderr(std::process::Stdio::inherit())\n            .status()\n            .context(\"Failed to run osascript\")?;\n\n        if status.success() {\n            Ok(())\n        } else if status.code() == Some(1) {\n            // osascript exits 1 when the user dismisses the admin-privileges\n            // prompt. This is a benign abort, not an error — tag it with a\n            // dedicated Code so the frontend can react based on the code\n            // rather than matching on an English message.\n            Err(\n                anyhow!(\"osascript exited with status 1\").context(ErrorContext::new_static(\n                    Code::CliInstallCancelled,\n                    \"CLI install cancelled\",\n                )),\n            )\n        } else {\n            Err(anyhow!(\n                \"osascript exited with status {}\",\n                status\n                    .code()\n                    .map(|c| c.to_string())\n                    .unwrap_or_else(|| \"unknown\".into())\n            ))\n        }\n    } else {\n        Err(anyhow!(\n            \"Would probably need to run \\\"ln -sf '{}' '{UNIX_LINK_PATH}'\\\"{privilege}\",\n            cli_path.display(),\n            privilege = if can_elevate_privileges {\n                \" with root permissions\"\n            } else {\n                \"\"\n            }\n        ))\n    }","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-action/src/cli.rs#L73-L109","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before: osascript exited with status 2 (privileged ln failed)\n# after: perform the link manually\nsudo mkdir -p /usr/local/bin\nsudo ln -sf \"$APP_CLI_PATH\" /usr/local/bin/but\nbut --version","handlingStrategy":"try-catch","validationCode":"// pre-flight the target dir before triggering elevation\nlet ok = std::fs::symlink_metadata(\"/usr/local/bin\")\n    .map(|m| m.is_dir())\n    .unwrap_or(false);\nif !ok {\n    // install into a user PATH dir instead of elevating\n}","typeGuard":null,"tryCatchPattern":"match do_install_cli(mode) {\n    Err(e) if e.to_string().starts_with(\"osascript exited with status\") => {\n        // fall back to printing or running the manual `ln -sf` instruction\n    }\n    r => r,\n}","preventionTips":["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"],"tags":["macos","cli-install","privileges","osascript","symlink"],"backgroundTag":"privilege-elevation-failed","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}