can1357/oh-my-pi · error · Error

brew update failed with exit code ${update.exitCode}

Error message

brew update failed with exit code ${update.exitCode}

What it means

Thrown in updateViaHomebrew when `brew update` (refreshing Homebrew's formula index) exits non-zero, before the actual `brew upgrade` is attempted. The CLI aborts the Homebrew update path because a stale formula index would install the wrong or missing version.

Source

Thrown at packages/coding-agent/src/cli/update-cli.ts:1659

	try {
		await steps.repair(launcherPath);
	} catch (err) {
		throw new Error(`${steps.manager} update did not produce a working launcher and binary repair failed: ${err}`, {
			cause: installError ?? err,
		});
	}
	console.log(
		chalk.yellow(
			`This install is no longer managed by ${steps.manager}. Removing the old global package may delete this launcher; if it does, reinstall with: ${installerHint()}`,
		),
	);
}

async function updateViaHomebrew(expectedVersion: string, force: boolean): Promise<void> {
	console.log(chalk.dim("Updating Homebrew formulae..."));
	const update = await $`brew update`.nothrow();
	if (update.exitCode !== 0) {
		throw new Error(`brew update failed with exit code ${update.exitCode}`);
	}

	console.log(chalk.dim("Updating via Homebrew..."));
	const args = buildHomebrewUpdateArgs(force);
	const result = await $`brew ${args}`.nothrow();
	if (result.exitCode !== 0) {
		throw new Error(`brew ${args[0]} failed with exit code ${result.exitCode}`);
	}

	await printVerification(expectedVersion);
}

async function updateViaMise(expectedVersion: string, force: boolean): Promise<void> {
	console.log(chalk.dim("Updating via mise..."));
	const args = buildMiseUpgradeArgs();
	const result = await $`mise ${args}`.nothrow();
	if (result.exitCode !== 0) {
		throw new Error(`mise upgrade failed with exit code ${result.exitCode}`);

View on GitHub (pinned to 9690622007)

Solutions

  1. Run `brew update -v` manually to see the underlying error
  2. Check network/proxy access to formulae.brew.sh and github.com
  3. Fix or untap broken taps reported by brew
  4. Repair Homebrew permissions (`sudo chown -R $(whoami) $(brew --prefix)/*` where applicable)
  5. Update manually: `brew update && brew upgrade <formula>`

Example fix

// before
const update = await $`brew update`.nothrow();
if (update.exitCode !== 0) {
	throw new Error(`brew update failed with exit code ${update.exitCode}`);
}
// after (diagnose)
const update = await $`brew update`.nothrow();
if (update.exitCode !== 0) {
	throw new Error(`brew update failed (${update.exitCode}): ${update.stderr.text()}`);
}
Defensive patterns

Strategy: retry

Validate before calling

const probe = await $`brew --repository`.nothrow();
if (probe.exitCode !== 0) throw new Error("Homebrew unavailable at expected path");

Type guard

function brewOk(r: { exitCode: number }): r is { exitCode: 0 } {
	return r.exitCode === 0;
}

Try / catch

try {
	await updateSelf({ method: "homebrew" });
} catch (err) {
	if (err.message.includes("brew update failed")) {
		await Bun.sleep(2000); // transient network/API flake: retry once
		await updateSelf({ method: "homebrew" });
	} else throw err;
}

Prevention

When it happens

Trigger: Self-update targets the homebrew method and `brew update` fails — no network to GitHub/Homebrew API, broken taps, HOMEBREW_API_DOMAIN misconfigured, or permissions problems in the Homebrew prefix.

Common situations: Offline/CI environments; corporate proxies blocking https://formulae.brew.sh; a broken third-party tap; macOS permission prompts (TMPDIR owned by root after restore).

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/4a9ffb34eae76247. Report an issue: GitHub.