Skip to content

Prime sudo before running the Homebrew installer - #2

Draft
mhfs wants to merge 1 commit into
mainfrom
fix-homebrew-sudo-noninteractive
Draft

mhfs wants to merge 1 commit into
mainfrom
fix-homebrew-sudo-noninteractive

Conversation

@mhfs

@mhfs mhfs commented Sep 18, 2026

Copy link
Copy Markdown
Member

The failure

Bootstrapping a freshly reformatted macOS 27 laptop aborted immediately:

==> Detected macOS 27.0 (arm64)
==> Installing Homebrew (this also installs the Xcode Command Line Tools)
==> sudo will ask for your password
==> Running in non-interactive mode because `$NONINTERACTIVE` is set.
==> Checking for `sudo` access (which may request your password)...
Need sudo access on macOS (e.g. the user mhfs needs to be an Administrator)!
error: Homebrew installation failed

Why

The account is an administrator — Homebrew's message is a red herring. We
invoke the installer with NONINTERACTIVE=1, and its have_sudo_access()
reacts to that by adding -n to sudo:

elif [[ -n "${NONINTERACTIVE-}" ]]
then
  SUDO+=("-n")
...
  "${SUDO[@]}" -l mkdir &>/dev/null

sudo -n fails outright instead of prompting. A machine that has just booted
has no cached sudo timestamp, so the pre-flight check fails and the installer
aborts. The ==> sudo will ask for your password line we printed one line
earlier was wrong for the same reason: NONINTERACTIVE=1 is precisely what
stopped it from asking.

This reproduces on any freshly booted Mac, so it hits every first-run
bootstrap — the exact case this script exists for.

The fix

Prime the sudo timestamp ourselves with a prompt-capable sudo -v before
handing off. Only the pre-flight check needed it: the installer's privileged
commands go through execute_sudo, which calls /usr/bin/sudo without
-n, so they re-prompt on their own if the timestamp expires during the
Command Line Tools download later in the run.

Details worth a look while reviewing:

  • prime_sudo opens with sudo -n -v, so a warm timestamp (or a passwordless
    sudo rule) short-circuits and we never announce a prompt that will not come.
  • The failure path is if sudo -v; then rather than sudo -v || die, because
    under set -euo pipefail the latter exits on sudo's status before the die
    diagnosis is ever printed.
  • On failure we now point at the one thing that would genuinely cause it —
    the account not being an administrator.

Testing

Not yet verified end to end on a clean macOS install — that is what keeps this
a draft. bash -n passes; the reasoning above is from Homebrew's current
install.sh. Worth a run on a fresh machine, or at least sudo -k followed by
the bootstrap command, before this merges.

🤖 Generated with Claude Code

On a freshly booted macOS machine the bootstrap aborted with:

    ==> Checking for `sudo` access (which may request your password)...
    Need sudo access on macOS (e.g. the user mhfs needs to be an Administrator)!
    error: Homebrew installation failed

The user is an administrator; the message is a red herring. We run the
Homebrew installer with NONINTERACTIVE=1, and its have_sudo_access() adds
`-n` to sudo whenever that variable is set:

    elif [[ -n "${NONINTERACTIVE-}" ]]
    then
      SUDO+=("-n")

so its pre-flight `sudo -l mkdir` check can never prompt. With no cached
sudo timestamp yet, it fails and the installer aborts.

Prime the timestamp ourselves first with a prompt-capable `sudo -v`. The
installer's privileged commands go through execute_sudo, which calls
/usr/bin/sudo without `-n`, so they re-prompt on their own if the
timestamp expires during the Command Line Tools download later in the
run; only the pre-flight check needed priming.

Also drop the "sudo will ask for your password" line that preceded the
installer, since NONINTERACTIVE=1 is exactly what stopped it from
asking. The replacement is printed only when a prompt is really coming.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant