jackwener/OpenCLI · critical · CommandExecutionError
${label} request failed: ${err?.message ?? err}
Error message
${label} request failed: ${err?.message ?? err} What it means
openalexFetch wraps all HTTP access to api.openalex.org and throws CommandExecutionError when the fetch itself rejects (network-level failure, before any HTTP status is seen). The message includes the labeled operation and the underlying error, with a hint to check reachability of api.openalex.org. This distinguishes transport failure from HTTP error statuses like 404 or 429.
Source
Thrown at clis/openalex/utils.js:87
return `doi:${doiUrl[1]}`;
}
// 5) bare 10.xxxx/yyy DOI
if (DOI_BARE.test(raw)) {
return `doi:${raw}`;
}
throw new ArgumentError(
`openalex work id "${value}" is not recognised`,
'Use a Work id ("W2741809807"), a DOI ("10.7717/peerj.4375"), or a full openalex.org / doi.org URL.',
);
}
export async function openalexFetch(url, label) {
let resp;
try {
resp = await fetch(url, { headers: { 'user-agent': UA, accept: 'application/json' } });
}
catch (err) {
throw new CommandExecutionError(
`${label} request failed: ${err?.message ?? err}`,
'Check that api.openalex.org is reachable from this network.',
);
}
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*"([^"]+)"/);View on GitHub (pinned to 49907e53dc)
Solutions
- Check network connectivity and that https://api.openalex.org resolves/reachable (curl it)
- Configure proxy env vars (HTTPS_PROXY) if behind a corporate proxy
- Retry after a short wait if it was a transient drop; consider adding a timeout/retry wrapper
- Inspect the inner err.message in the error text for the specific socket/DNS cause
Example fix
// before
const works = await openalexSearch(q); // throws on any network blip
// after
const works = await withRetry(3, () => openalexSearch(q));
function withRetry(n, fn) {
return fn().catch(e => n > 1 ? withRetry(n - 1, fn) : Promise.reject(e));
} Defensive patterns
Strategy: retry
Try / catch
try {
const data = await openalexFetch(url, 'openalex work');
} catch (e) {
if (e.name === 'CommandExecutionError' && e.message.includes('request failed')) {
// network-level failure: check connectivity/proxy, retry with backoff
await sleep(1000);
return openalexFetch(url, 'openalex work');
}
throw e;
} Prevention
- Set HTTPS_PROXY/HTTP_PROXY in restricted networks
- Wrap API calls in a retry helper with exponential backoff
- Verify api.openalex.org reachability (curl) as an environment smoke test
- Surface the inner err.message when logging for faster diagnosis
When it happens
Trigger: fetch() rejecting due to DNS failure, no route to host, TLS errors, connection refused/timeout, or an offline network while calling any openalex command (search, ref, etc.).
Common situations: Corporate proxy or firewall blocking api.openalex.org; VPN required but not connected; DNS misconfiguration; IPv6 issues; ephemeral network drops in CI.
Related errors
- ${label} request failed: ${err?.message ?? err}
- ${label} returned HTTP ${resp.status}${detail}
- ${label} returned malformed JSON: ${err?.message ?? err}
- FETCH_ERROR
- wikipedia page request failed: ${error?.message || error}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/d92240c7fefc82d4.
Report an issue: GitHub.