jackwener/OpenCLI · warning · EmptyResultError
Semantic Scholar returned 404 for ${url}.
Error message
Semantic Scholar returned 404 for ${url}. What it means
s2Fetch maps an HTTP 404 from the Semantic Scholar API to EmptyResultError with the full request URL in the message. Semantically, 404 means the requested resource (paper id, citation set, recommendation set) does not exist, so the library treats it as an empty result rather than a hard failure — enabling uniform no-data handling in scripts.
Source
Thrown at clis/semanticscholar/utils.js:113
while (true) {
try {
resp = await fetch(url, { headers });
} catch (err) {
throw new CommandExecutionError(
`${label} request failed: ${err?.message ?? err}`,
'Check that api.semanticscholar.org is reachable from this network.',
);
}
if (resp.status === 429 && attempt === 0 && !apiKey) {
attempt += 1;
await new Promise(resolve => setTimeout(resolve, 1500));
continue;
}
break;
}
if (resp.status === 404) {
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}`);View on GitHub (pinned to 49907e53dc)
Solutions
- Validate the reference: re-run `opencli semanticscholar search "<title>"` and use the paperId from results.
- Double-check the id for typos and that it is currently valid (try the DOI or arXiv form instead).
- If using a typed prefix, confirm the id under that prefix exists (e.g. PMID ids must exist in PubMed).
- In scripts, catch EmptyResultError and skip/log the id instead of aborting.
Example fix
// before opencli semanticscholar paper "10.9999/nonexistent-doi" // after opencli semanticscholar search "Attention Is All You Need" opencli semanticscholar paper "ARXIV:1706.03762"
Defensive patterns
Strategy: try-catch
Validate before calling
// validate ref format before calling (avoids most 404s)
if (!isRecognizedPaperRef(ref)) throw new Error(`unrecognized paper ref: ${ref}`); Try / catch
try {
const paper = await fetchPaper(ref);
} catch (err) {
if (err instanceof EmptyResultError) {
console.warn(`Not found on Semantic Scholar: ${ref}; skipping.`);
return null;
}
throw err;
} Prevention
- Resolve references through `semanticscholar search` instead of trusting external id databases.
- Watch for retired id spaces (MAG ids) and stale cached paperIds in your data.
- Log the URL from the error message to confirm which id 404'd.
- Maintain a skip-list of ids that repeatedly 404 in batch jobs.
When it happens
Trigger: Calling `paper`/`citations`/`recommendations` with an id the API cannot resolve: a typo in a 40-hex paperId, a deleted/merged paper, an ARXIV:/DOI:/PMID: id that Semantic Scholar has no record for, or a CorpusId that does not exist.
Common situations: Hardcoded ids copied from another database (MAG ids retired after MAG shutdown); stale cached paperIds; DOIs of papers never ingested by Semantic Scholar; scripts feeding ids from an outdated export.
Related errors
- ${label} returned 404 (no matches).
- Homebrew API returned 404 for ${url}.
- No posts found for "${keyword}"
- Lichess returned 404 for ${url}.
- openFDA returned no labels matching "${query}".
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/bd664559bdb11f37.
Report an issue: GitHub.