jackwener/OpenCLI · error · CommandExecutionError
semanticscholar citations row is missing citingPaper
Error message
semanticscholar citations row is missing citingPaper
What it means
The citations endpoint returns rows shaped `{ data: [{ citingPaper: {...} }] }`. Before unwrapping, each row is checked (clis/semanticscholar/citations.js:56): if an entry is null, not an object, or lacks a `citingPaper` key, this CommandExecutionError is thrown. It indicates the API violated its documented per-row contract.
Source
Thrown at clis/semanticscholar/citations.js:56
throw new ArgumentError('semanticscholar citations offset must be a non-negative integer');
}
if (offset > 9999) {
throw new ArgumentError('semanticscholar citations offset must be <= 9999');
}
const url = `${S2_GRAPH_BASE}/paper/${encodeURIComponent(ref)}/citations?fields=${FIELDS}&limit=${limit}&offset=${offset}`;
const body = await s2Fetch(url, 'semanticscholar citations');
const data = Array.isArray(body?.data) ? body.data : null;
if (data === null) {
throw new CommandExecutionError('semanticscholar citations returned an unexpected payload shape');
}
if (!data.length) {
throw new EmptyResultError('semanticscholar citations', `No Semantic Scholar citations for "${args.id}" at offset ${offset}.`);
}
return data.slice(0, limit).map((entry, i) => {
if (!entry || typeof entry !== 'object' || !('citingPaper' in entry)) {
throw new CommandExecutionError('semanticscholar citations row is missing citingPaper');
}
return normalizePaperRow(entry.citingPaper, 'citations', { rank: offset + i + 1 });
});
},
});
View on GitHub (pinned to 49907e53dc)
Solutions
- Dump the raw response (curl the same URL) and inspect the offending row's shape.
- Retry — transient partial responses during S2 incidents usually resolve.
- Check the Semantic Scholar API docs/changelog for a citations response schema change and update the adapter.
- Filter or skip malformed rows client-side if you control the calling code.
- Report persistent occurrences with the paper id to Semantic Scholar support.
Example fix
// before return data.map((entry) => normalizePaperRow(entry.citingPaper, 'citations')); // after return data .filter((entry) => entry && typeof entry === 'object' && 'citingPaper' in entry) .map((entry) => normalizePaperRow(entry.citingPaper, 'citations'));
Defensive patterns
Strategy: type-guard
Validate before calling
function rowHasCitingPaper(entry) {
return Boolean(entry) && typeof entry === 'object' && 'citingPaper' in entry;
}
// filter before mapping:
const usable = data.filter(rowHasCitingPaper); Type guard
function isCitationEntry(entry) {
return typeof entry === 'object' && entry !== null
&& 'citingPaper' in entry
&& typeof entry.citingPaper === 'object'
&& entry.citingPaper !== null
&& typeof entry.citingPaper.title === 'string';
} Try / catch
try {
rows = await citations(id, offset);
} catch (err) {
if (/missing citingPaper/.test(err.message)) {
console.error('S2 citations row schema violation; inspecting raw payload...');
// fetch raw body for diagnosis, retry once
return citations(id, offset);
}
throw err;
} Prevention
- Validate rows defensively (filter instead of throwing) in your own wrappers.
- Keep an eye on Semantic Scholar API changelogs for citations schema changes.
- Retry once on row-level contract violations — they are often incident-related partial responses.
- Save a sample raw response per paper id when reporting persistent issues.
When it happens
Trigger: A row in body.data is null or a primitive; the API returns citations entries keyed differently (schema drift); partial/soft-error bodies that happen to include a top-level data array but not the citingPaper wrapper.
Common situations: Semantic Scholar A/B-testing or rolling out an API schema change; degraded/partial responses during incidents where rows come back null; a cached or proxied response with an older/newer shape.
Related errors
- semanticscholar citations returned an unexpected payload sha
- semanticscholar paper returned an unexpected payload shape
- semanticscholar recommendations returned an unexpected paylo
- Xiaoyuzhou playback progress pid did not match history eid $
- Bilibili view API returned duplicate page entries for p=${pa
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/533fba8e52f48870.
Report an issue: GitHub.