jackwener/OpenCLI · error · CommandExecutionError
${label} returned HTTP ${resp.status}
Error message
${label} returned HTTP ${resp.status} What it means
brewFetch throws this generic CommandExecutionError for any non-OK HTTP status that isn't the specially-handled 404 or 429 — e.g. 500/502/503 from GitHub Pages, 403 from a WAF, or unusual proxies' error pages. The message carries the label and the raw status code since the API has no structured error body to surface.
Source
Thrown at clis/homebrew/utils.js:81
resp = await fetch(url, { headers: { 'user-agent': UA, accept: 'application/json' } });
}
catch (err) {
throw new CommandExecutionError(
`${label} request failed: ${err?.message ?? err}`,
'Check that formulae.brew.sh is reachable from this network.',
);
}
if (resp.status === 404) {
throw new EmptyResultError(label, `Homebrew API returned 404 for ${url}.`);
}
if (resp.status === 429) {
throw new CommandExecutionError(
`${label} returned HTTP 429 (rate limited)`,
'Homebrew throttles bursts; wait a few seconds and retry.',
);
}
if (!resp.ok) {
throw new CommandExecutionError(`${label} returned HTTP ${resp.status}`);
}
let body;
try {
body = await resp.json();
}
catch (err) {
throw new CommandExecutionError(`${label} returned malformed JSON: ${err?.message ?? err}`);
}
return body;
}
/** Coerce a count value (which Homebrew analytics serves as `"139,972"`) to a plain number. */
export function parseInstallCount(value) {
if (value == null) return null;
const s = String(value).replace(/,/g, '').trim();
if (!s) return null;
const n = Number(s);
return Number.isFinite(n) ? n : null;View on GitHub (pinned to 49907e53dc)
Solutions
- Check the Homebrew/GitHub Pages status and retry later for 5xx — the API is regenerated daily and outages are usually brief.
- Verify with curl -I what status the URL returns and whether a proxy is injecting the error.
- For 403, whitelist formulae.brew.sh in the proxy/firewall or exempt the domain from TLS inspection.
- Wrap calls in retry-with-backoff for transient 5xx.
Example fix
// before
const data = await brewFetch(url, 'formula info'); // 503 during outage -> throws
// after
let data;
for (let attempt = 1; attempt <= 3; attempt++) {
try { data = await brewFetch(url, 'formula info'); break; }
catch (err) {
if (/HTTP 5\d\d/.test(err.message) && attempt < 3) { await sleep(2 ** attempt * 1000); continue; }
throw err;
}
} Defensive patterns
Strategy: retry
Validate before calling
null
Type guard
null
Try / catch
try {
const data = await brewFetch(url, label);
} catch (err) {
if (err instanceof CommandExecutionError && /HTTP \d{3}/.test(err.message) && !/HTTP (404|429)/.test(err.message)) {
// 5xx/other: transient or upstream — retry with backoff or degrade gracefully
return getCachedOrEmpty(label);
}
throw err;
} Prevention
- Subscribe to Homebrew/GitHub Pages status pages for outage awareness.
- Wrap calls in retry-with-exponential-backoff for 5xx.
- Check for corporate proxies/TLS inspection that inject non-API responses.
- Degrade gracefully: serve stale cached data when the API is down.
When it happens
Trigger: Any brewFetch-based call while formulae.brew.sh / GitHub Pages returns a 5xx outage or 403; a middlebox (corporate proxy, SSL-inspection appliance) intercepting and returning its own error status.
Common situations: Homebrew API or GitHub Pages incidents (check status); corporate proxies blocking the domain with 403; misconfigured egress gateways returning 5xx; transient upstream hiccups during a deploy of the static API.
Related errors
- API_ERROR
- API_ERROR
- arXiv API HTTP ${resp.status}
- coingecko categories returned HTTP ${resp.status}
- coingecko coin failed: HTTP ${resp.status}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/47cb3f3c75cd830e.
Report an issue: GitHub.