jackwener/OpenCLI · error · CommandExecutionError
${label} returned HTTP ${resp.status}${detail}
Error message
${label} returned HTTP ${resp.status}${detail} What it means
openalexFetch wraps every OpenAlex REST call and converts non-ok HTTP statuses (other than 404/429, which get their own errors) into a CommandExecutionError carrying the status code plus any "message" field extracted from the error body. It exists so callers get a consistent, labeled failure instead of a raw fetch/HTTP object. The interpolated detail comes from parsing the response text for a JSON "message" key.
Source
Thrown at clis/openalex/utils.js:109
}
if (resp.status === 404) {
throw new EmptyResultError(label, `OpenAlex returned 404 for ${url}.`);
}
if (resp.status === 429) {
throw new CommandExecutionError(
`${label} returned HTTP 429 (rate limited)`,
'OpenAlex throttles unauthenticated traffic; wait a few seconds and retry, or set OPENALEX_MAILTO.',
);
}
if (!resp.ok) {
let detail = '';
try {
const text = await resp.text();
const match = text.match(/"message"\s*:\s*"([^"]+)"/);
if (match) detail = ` (${match[1]})`;
}
catch { /* ignore */ }
throw new CommandExecutionError(`${label} returned HTTP ${resp.status}${detail}`);
}
let body;
try {
body = await resp.json();
}
catch (err) {
throw new CommandExecutionError(`${label} returned malformed JSON: ${err?.message ?? err}`);
}
return body;
}
/** Strip the `https://openalex.org/` prefix if present so columns surface just the bare id. */
export function bareId(value) {
const s = String(value ?? '').trim();
if (!s) return '';
return s.replace(/^https?:\/\/(?:api\.)?openalex\.org\//i, '').replace(/^works\//i, '');
}
View on GitHub (pinned to 49907e53dc)
Solutions
- Read the interpolated detail in the message — it contains OpenAlex's own error "message" from the response body, which usually names the bad parameter.
- Print/log the full URL that was fetched and validate each query parameter (filters, per-page, sort) against the OpenAlex API docs.
- Retry once after a short wait in case of a transient 5xx, and check the OpenAlex status page.
- Escape and re-encode user-supplied query terms with encodeURIComponent before building the URL.
Example fix
// before
const url = `${OPENALEX_BASE}/works?filter=${rawUserFilter}`;
// after
const url = `${OPENALEX_BASE}/works?filter=${encodeURIComponent(rawUserFilter)}`; Defensive patterns
Strategy: try-catch
Validate before calling
function validateOpenAlexQuery(params) {
for (const [k, v] of Object.entries(params)) {
if (v == null || v === '') throw new Error(`openalex param "${k}" is empty`);
}
return true;
} Type guard
function isHttpError(e) {
return e instanceof Error && /returned HTTP \d+/.test(e.message);
} Try / catch
try {
const body = await openalexFetch(url, 'openalex works');
} catch (e) {
const m = e.message.match(/returned HTTP (\d+)/);
if (m && Number(m[1]) >= 500) { /* retry after delay */ }
else { /* surface e.message (contains API detail) to the user */ }
} Prevention
- encodeURIComponent every user-supplied query/filter value.
- Validate filters against the OpenAlex filter docs before sending.
- Retry transient 5xx with exponential backoff.
- Check api.openalex.org reachability before large batch runs.
When it happens
Trigger: An OpenAlex request resolves but returns a non-ok, non-404/429 status — e.g. HTTP 400 for a malformed query string, 403 for a blocked user agent, or 5xx when OpenAlex is degraded. Any command that calls openalexFetch (works lookup by id/DOI, search listings) can hit it.
Common situations: A malformed filter/query parameter produces 400 from api.openalex.org; a corporate proxy or firewall returns 403; OpenAlex has a transient 5xx outage; an invalid entity id path slips past validation and yields an unexpected status.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- ${label} returned HTTP ${resp.status}: ${summarizeApiError(p
- HTTP ${result.httpStatus} from /api/organizations
- ${label} returned HTTP ${res.status}
- HTTP_ERROR
- HTTP_ERROR
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/f0b85a391ef3b4b7.
Report an issue: GitHub.