jackwener/OpenCLI · error · CommandExecutionError

semanticscholar ${label} row is missing title

Error message

semanticscholar ${label} row is missing title

What it means

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.

Source

Thrown at clis/semanticscholar/utils.js:170

}

export function optionalNumber(value, label) {
    if (value == null) return null;
    if (typeof value !== 'number' || !Number.isFinite(value)) {
        throw new CommandExecutionError(`semanticscholar ${label} must be a number when present`);
    }
    return value;
}

export function normalizePaperRow(paper, label, { rank } = {}) {
    if (!paper || typeof paper !== 'object') {
        throw new CommandExecutionError(`semanticscholar ${label} row is not an object`);
    }
    if (typeof paper.paperId !== 'string' || !paper.paperId.trim()) {
        throw new CommandExecutionError(`semanticscholar ${label} row is missing paperId`);
    }
    if (typeof paper.title !== 'string' || !paper.title.trim()) {
        throw new CommandExecutionError(`semanticscholar ${label} row is missing title`);
    }
    if (paper.authors != null && !Array.isArray(paper.authors)) {
        throw new CommandExecutionError(`semanticscholar ${label} row has malformed authors`);
    }
    const row = {
        paperId: paper.paperId.trim(),
        doi: pickDoi(paper.externalIds),
        title: paper.title.trim(),
        year: optionalNumber(paper.year, `${label} year`),
        firstAuthor: firstAuthorName(paper.authors),
        citationCount: optionalNumber(paper.citationCount, `${label} citationCount`),
        url: typeof paper.url === 'string' && paper.url.trim()
            ? paper.url.trim()
            : `https://www.semanticscholar.org/paper/${paper.paperId.trim()}`,
    };
    if (rank != null) return { rank, ...row };
    return row;
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Include `title` in the `fields` query parameter of the API request.
  2. Filter or substitute rows lacking titles before normalizePaperRow.
  3. Fall back to a placeholder title ('(untitled)') for incomplete records if acceptable.
  4. Retry with a different identifier (DOI/arXiv) that resolves to a fully indexed record.

Example fix

// before
fetch(`${S2_GRAPH_BASE}/paper/${ref}?fields=paperId`)
// after
fetch(`${S2_GRAPH_BASE}/paper/${ref}?fields=paperId,title,authors,year,citationCount`)
Defensive patterns

Strategy: validation

Validate before calling

const url = `${S2_GRAPH_BASE}/paper/${ref}?fields=paperId,title,authors,year,citationCount`;
const titled = rows.filter(r => typeof r?.title === 'string' && r.title.trim());

Type guard

function hasTitle(v) {
  return v !== null && typeof v === 'object' && typeof v.title === 'string' && v.title.trim().length > 0;
}

Try / catch

try {
  return normalizePaperRow(paper, 'citation');
} catch (err) {
  if (/missing title/.test(err.message)) {
    return normalizePaperRow({ ...paper, title: '(untitled)' }, 'citation');
  }
  throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/60d801d80785c29d. Report an issue: GitHub.