{"record":{"id":"bbc56ea2c33065c8","repo":"jackwener/OpenCLI","slug":"semanticscholar-label-row-has-malformed-authors","errorCode":null,"errorMessage":"semanticscholar ${label} row has malformed authors","messagePattern":"semanticscholar (.+?) row has malformed authors","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/semanticscholar/utils.js","lineNumber":173,"sourceCode":"    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    };\n    if (rank != null) return { rank, ...row };\n    return row;\n}\n\n/** Strip the typed prefix from `externalIds.DOI` and similar. */\nexport function pickDoi(externalIds) {","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/semanticscholar/utils.js#L155-L191","documentation":"normalizePaperRow tolerates a missing authors field but rejects one that is present and not an array (`paper.authors != null && !Array.isArray(paper.authors)`), throwing this CommandExecutionError. It enforces that author data, when supplied, follows the expected [{name: string}] shape.","triggerScenarios":"The API (or an intermediary/proxy) returns authors as an object, string, or other non-array value on a paper row that normalizePaperRow is processing.","commonSituations":"Semantic Scholar schema drift changing the authors container; a proxy caching an older response shape; hand-written fixtures with authors: 'Smith, J.' instead of an array.","solutions":["Inspect the raw row's authors value and conform the fixture/caller to an array of {name} objects.","Coerce common shapes: wrap a single author string in [{name: s}] or extract Object.values if it's an object map.","Check for API version changes and update the adapter's field handling.","Drop the malformed field (set authors to null) so firstAuthorName returns '' instead of failing."],"exampleFix":"// before\nauthors: paper.authors,\n// after: coerce or null out malformed authors\nlet authors = paper.authors;\nif (authors != null && !Array.isArray(authors)) {\n  authors = typeof authors === 'string' ? [{ name: authors }] : null;\n}","handlingStrategy":"type-guard","validationCode":"function sanitizeAuthors(a) {\n  if (a == null) return null;\n  if (Array.isArray(a)) return a;\n  if (typeof a === 'string' && a.trim()) return [{ name: a.trim() }];\n  return null; // drop malformed shapes\n}","typeGuard":"function isAuthorList(v) {\n  return v == null || (Array.isArray(v) && v.every(x => x && typeof x === 'object' && typeof x.name === 'string'));\n}","tryCatchPattern":"try {\n  return normalizePaperRow(paper, 'citation');\n} catch (err) {\n  if (/malformed authors/.test(err.message)) {\n    return normalizePaperRow({ ...paper, authors: null }, 'citation');\n  }\n  throw err;\n}","preventionTips":["Normalize authors to an array of {name} objects at ingestion time.","Validate fixtures against the expected row shape before use.","Watch for S2 schema changes affecting the authors field."],"tags":["validation","type-error","data-shape","semantic-scholar"],"backgroundTag":"schema-validation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}