{"record":{"id":"90e9af47cf343dac","repo":"jackwener/OpenCLI","slug":"semanticscholar-label-row-is-missing-paperid","errorCode":null,"errorMessage":"semanticscholar ${label} row is missing paperId","messagePattern":"semanticscholar (.+?) row is missing paperId","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/semanticscholar/utils.js","lineNumber":167,"sourceCode":"        return first.name.trim();\n    }\n    return '';\n}\n\nexport function optionalNumber(value, label) {\n    if (value == null) return null;\n    if (typeof value !== 'number' || !Number.isFinite(value)) {\n        throw new CommandExecutionError(`semanticscholar ${label} must be a number when present`);\n    }\n    return value;\n}\n\nexport function normalizePaperRow(paper, label, { rank } = {}) {\n    if (!paper || typeof paper !== 'object') {\n        throw new CommandExecutionError(`semanticscholar ${label} row is not an object`);\n    }\n    if (typeof paper.paperId !== 'string' || !paper.paperId.trim()) {\n        throw new CommandExecutionError(`semanticscholar ${label} row is missing paperId`);\n    }\n    if (typeof paper.title !== 'string' || !paper.title.trim()) {\n        throw new CommandExecutionError(`semanticscholar ${label} row is missing title`);\n    }\n    if (paper.authors != null && !Array.isArray(paper.authors)) {\n        throw new CommandExecutionError(`semanticscholar ${label} row has malformed authors`);\n    }\n    const row = {\n        paperId: paper.paperId.trim(),\n        doi: pickDoi(paper.externalIds),\n        title: paper.title.trim(),\n        year: optionalNumber(paper.year, `${label} year`),\n        firstAuthor: firstAuthorName(paper.authors),\n        citationCount: optionalNumber(paper.citationCount, `${label} citationCount`),\n        url: typeof paper.url === 'string' && paper.url.trim()\n            ? paper.url.trim()\n            : `https://www.semanticscholar.org/paper/${paper.paperId.trim()}`,\n    };","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/semanticscholar/utils.js#L149-L185","documentation":"normalizePaperRow requires every paper row to carry a non-empty string paperId, the canonical Semantic Scholar identifier. A row that is an object but lacks paperId (empty, missing, or non-string) triggers this error. paperId is required because the adapter derives the paper URL from it.","triggerScenarios":"A citation/reference/recommendations row is an object but its paperId field is missing, empty string, or whitespace-only — often for records where S2 hasn't ingested full metadata.","commonSituations":"Newly indexed or partially ingested papers lacking ids; API field selection omitting paperId from the `fields` query param so the response never includes it.","solutions":["Ensure the request's `fields` query parameter includes `paperId` (and `title`).","Filter out rows without paperId before normalizing.","Retry with a canonical ref (DOI or arXiv id) if a specific record is incomplete.","Check whether the API version changed row shape and update the adapter."],"exampleFix":"// before\nfetch(`${S2_GRAPH_BASE}/paper/${ref}/citations?fields=title`)\n// after\nfetch(`${S2_GRAPH_BASE}/paper/${ref}/citations?fields=paperId,title,year,authors,citationCount`)","handlingStrategy":"validation","validationCode":"// Request paperId explicitly and pre-filter rows\nconst url = `${S2_GRAPH_BASE}/paper/${ref}/citations?fields=paperId,title,year,authors,citationCount`;\nconst usable = (data.data ?? []).filter(r => typeof r?.paperId === 'string' && r.paperId.trim());","typeGuard":"function hasPaperId(v) {\n  return v !== null && typeof v === 'object' && typeof v.paperId === 'string' && v.paperId.trim().length > 0;\n}","tryCatchPattern":"try {\n  return normalizePaperRow(paper, 'citation');\n} catch (err) {\n  if (/missing paperId/.test(err.message)) return null; // skip incomplete record\n  throw err;\n}","preventionTips":["Always include paperId in the `fields` query parameter.","Pre-filter rows lacking paperId instead of failing the whole command.","Prefer canonical identifiers (DOI/arXiv) for records likely fully indexed."],"tags":["validation","missing-field","data-shape","semantic-scholar"],"backgroundTag":"missing-required-field","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}