jackwener/OpenCLI · error · CommandExecutionError
${label} returned an error: ${body.error}
Error message
${label} returned an error: ${body.error} What it means
When the Semantic Scholar response parses as JSON but contains a truthy `error` field (API-level error object inside a 200 or ok response), s2Fetch surfaces it as CommandExecutionError `${label} returned an error: ${body.error}`. This is the API's own application error, not a transport failure.
Source
Thrown at clis/semanticscholar/utils.js:131
throw new EmptyResultError(label, `Semantic Scholar returned 404 for ${url}.`);
}
if (resp.status === 429) {
throw new CommandExecutionError(
`${label} returned HTTP 429 (rate limited)`,
'Semantic Scholar throttles anonymous traffic; set SEMANTIC_SCHOLAR_API_KEY (free at https://www.semanticscholar.org/product/api) or wait a minute 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}`);
}
if (body && typeof body === 'object' && body.error) {
throw new CommandExecutionError(`${label} returned an error: ${body.error}`);
}
return body;
}
/** Return the AI-generated one-line summary if present, else ''. */
export function tldrText(tldr) {
if (tldr && typeof tldr === 'object' && typeof tldr.text === 'string') {
return tldr.text.trim();
}
return '';
}
/** First author display name, or '' when authors is missing. */
export function firstAuthorName(authors) {
if (!Array.isArray(authors) || !authors.length) return '';
const first = authors[0];
if (first && typeof first === 'object' && typeof first.name === 'string') {
return first.name.trim();View on GitHub (pinned to 49907e53dc)
Solutions
- Read body.error from the message for the API's own explanation.
- For recommendations errors, try a different or better-known paper ref (DOI or canonical S2 paperId).
- Re-check the query string: remove invalid fields or parameters the API flagged.
- Retry later if the error indicates a backend problem; otherwise fix the request payload.
Example fix
// before
const recs = await s2Fetch(`${S2_REC_BASE}/papers/forpaper/${ref}?fields=title`, 'recommendations');
// after: fall back when the API reports an in-band error
try {
const recs = await s2Fetch(`${S2_REC_BASE}/papers/forpaper/${ref}?fields=title`, 'recommendations');
} catch (e) {
if (/returned an error/.test(e.message)) return []; // no recommendations available
throw e;
} Defensive patterns
Strategy: fallback
Type guard
function hasApiError(body) {
return body !== null && typeof body === 'object' && 'error' in body && Boolean(body.error);
} Try / catch
try {
return await s2Fetch(url, 'recommendations');
} catch (err) {
if (/returned an error/.test(err.message)) {
return { recommendations: [] }; // graceful empty fallback
}
throw err;
} Prevention
- Use canonical refs (DOI, arXiv id, or 40-hex paperId) for best API coverage.
- Treat in-band API errors as 'no data' for optional features like recommendations.
- Log body.error content to spot recurring request-shape problems.
When it happens
Trigger: The graph/recommendations API returns {"error": ...} — e.g. invalid query combination, dataset not found, or recommendations backend unable to produce suggestions for the given paperId.
Common situations: Calling recommendations for a paper with no embedding (obscure/new papers), malformed CorpusId, or Semantic Scholar returning structured API errors while still sending a 2xx status.
Related errors
- ${label} returned HTTP ${resp.status}
- API_ERROR
- API_ERROR
- ${label} returned HTTP ${resp.status}: ${summarizeApiError(p
- No user message found in request
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/988fd3877b1b50e4.
Report an issue: GitHub.