multica-ai/multica · error
brew upgrade failed: %w
Error message
brew upgrade failed: %w
What it means
UpdateViaBrew shells out to `brew upgrade multica-ai/tap/multica` and wraps any non-zero exit with 'brew upgrade failed: %w'. The wrapped error is an *exec.ExitError plus the captured CombinedOutput is returned alongside it. This is the self-update path used when the running binary is detected as a Homebrew install (IsBrewInstall).
Source
Thrown at server/internal/cli/update.go:335
func GetBrewPrefix() string {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
cmd := exec.CommandContext(ctx, "brew", "--prefix")
cmd.WaitDelay = 2 * time.Second
out, err := cmd.Output()
if err != nil {
return ""
}
return strings.TrimSpace(string(out))
}
// UpdateViaBrew runs `brew upgrade multica-ai/tap/multica`.
// Returns the combined output and any error.
func UpdateViaBrew() (string, error) {
cmd := exec.Command("brew", "upgrade", "multica-ai/tap/multica")
out, err := cmd.CombinedOutput()
if err != nil {
return string(out), fmt.Errorf("brew upgrade failed: %w", err)
}
return string(out), nil
}
func updateDownloadTimeoutOrDefault(timeout time.Duration) time.Duration {
if timeout <= 0 {
return DefaultUpdateDownloadTimeout
}
return timeout
}
// fetchURLBytes does a GET with the given timeout and returns the response
// body in full. Used for the checksum manifest (tiny) and the release
// archive (single-digit MB). The checksum verification path requires buffered
// bytes so streaming would just push the buffer into the caller anyway.
func fetchURLBytes(url string, timeout time.Duration) ([]byte, error) {
client := &http.Client{Timeout: updateDownloadTimeoutOrDefault(timeout)}
resp, err := client.Get(url)View on GitHub (pinned to 2c0912b6ec)
Solutions
- Read the returned output string — brew prints the actual reason (unknown formula, permission, network) to stderr and it is included in the first return value.
- Verify Homebrew is installed and on PATH: `which brew` (exec.LookPath("brew") in code).
- Fix ownership of the brew prefix (e.g. `sudo chown -R $(whoami) /opt/homebrew`) or rerun the update in a shell where brew works.
- Repair the tap: `brew tap multica-ai/tap` then retry the upgrade.
- If brew is fundamentally unavailable, fall back to the download-based updater (UpdateViaDownload) instead of the brew path.
Example fix
// before
out, err := cli.UpdateViaBrew()
if err != nil {
log.Fatal(err) // loses brew's own diagnostics
}
// after
out, err := cli.UpdateViaBrew()
if err != nil {
log.Printf("brew update failed: %v\nbrew output:\n%s", err, out)
if _, lookErr := exec.LookPath("brew"); lookErr != nil {
log.Printf("falling back to download-based update")
out, err = cli.UpdateViaDownload(targetVersion)
}
} Defensive patterns
Strategy: fallback
Validate before calling
if _, err := exec.LookPath("brew"); err != nil {
// brew unavailable; do not attempt UpdateViaBrew
}
if !cli.IsBrewInstall() {
// not a brew-managed binary; use UpdateViaDownload instead
} Type guard
func isExitError(err error) bool {
var ee *exec.ExitError
return errors.As(err, &ee)
} Try / catch
out, err := cli.UpdateViaBrew()
if err != nil {
log.Printf("brew update failed: %v\noutput: %s", err, out)
if !isExitError(err) {
return err // brew missing/launch failure, not a brew-level failure
}
out, err = cli.UpdateViaDownload(latest)
} Prevention
- Gate the brew path on cli.IsBrewInstall() before calling UpdateViaBrew
- Always log the returned output string — brew's stderr explains the exit
- Verify brew is on PATH with exec.LookPath before updating
When it happens
Trigger: Running the CLI update command on a machine where Homebrew is not installed or not on PATH; the tap multica-ai/tap no longer exists or was renamed; the formula is already up to date combined with a brew quirk; brew lacking write permission to its prefix (sudo-owned /opt/homebrew or /usr/local); network failure reaching github.com while brew fetches the bottle.
Common situations: CI runners with minimal images that lack brew; a user installed via the download path but a brew prefix string accidentally matches MatchKnownBrewPrefix; macOS System Integrity/permission prompts after a macOS upgrade; an offline or firewalled environment.
Related errors
- brew upgrade failed: %w You can try manually: brew upgrade m
- no matching release asset for %s/%s (tried: %s)
- resolve executable path: %w
- resolve symlink: %w
- stat original binary: %w
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/12b430e6106e55df.
Report an issue: GitHub.