{"record":{"id":"60d801d80785c29d","repo":"jackwener/OpenCLI","slug":"semanticscholar-label-row-is-missing-title","errorCode":null,"errorMessage":"semanticscholar ${label} row is missing title","messagePattern":"semanticscholar (.+?) row is missing title","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/semanticscholar/utils.js","lineNumber":170,"sourceCode":"}\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    };\n    if (rank != null) return { rank, ...row };\n    return row;\n}","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/semanticscholar/utils.js#L152-L188","documentation":"normalizePaperRow requires a non-empty string `title` on each paper row; the adapter's table output depends on it. Rows whose title is missing, empty, or whitespace-only throw this CommandExecutionError. Like the paperId check, this guards the adapter's display contract.","triggerScenarios":"A paper record from citations/references/recommendations has no title — e.g. S2 only has a bare identifier for that record, or `title` was omitted from the `fields` param in the request URL.","commonSituations":"Very obscure or non-English records without indexed titles; requests built with a minimal fields list (e.g. `?fields=paperId`) that drop title; dataset dumps with placeholder rows.","solutions":["Include `title` in the `fields` query parameter of the API request.","Filter or substitute rows lacking titles before normalizePaperRow.","Fall back to a placeholder title ('(untitled)') for incomplete records if acceptable.","Retry with a different identifier (DOI/arXiv) that resolves to a fully indexed record."],"exampleFix":"// before\nfetch(`${S2_GRAPH_BASE}/paper/${ref}?fields=paperId`)\n// after\nfetch(`${S2_GRAPH_BASE}/paper/${ref}?fields=paperId,title,authors,year,citationCount`)","handlingStrategy":"validation","validationCode":"const url = `${S2_GRAPH_BASE}/paper/${ref}?fields=paperId,title,authors,year,citationCount`;\nconst titled = rows.filter(r => typeof r?.title === 'string' && r.title.trim());","typeGuard":"function hasTitle(v) {\n  return v !== null && typeof v === 'object' && typeof v.title === 'string' && v.title.trim().length > 0;\n}","tryCatchPattern":"try {\n  return normalizePaperRow(paper, 'citation');\n} catch (err) {\n  if (/missing title/.test(err.message)) {\n    return normalizePaperRow({ ...paper, title: '(untitled)' }, 'citation');\n  }\n  throw err;\n}","preventionTips":["Include title in the `fields` query parameter of every paper request.","Substitute a placeholder for untitled records if display requires it.","Prefer well-indexed records (DOI/arXiv refs) over obscure ids."],"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"}