{"record":{"id":"20194387f435b6c2","repo":"jackwener/OpenCLI","slug":"commandlabel-omitted-summaries-for-one-or-more","errorCode":null,"errorMessage":"${commandLabel} omitted summaries for one or more PMIDs","messagePattern":"(.+?) omitted summaries for one or more PMIDs","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/pubmed/utils.js","lineNumber":243,"sourceCode":"        article_type: articleTypeFromList(article?.pubtype),\n        doi: extractDoi(article?.articleids),\n        url: buildPubMedUrl(id),\n    };\n}\n\nexport function ensureCompleteSummaryRows(pmids, result, commandLabel) {\n    if (!result || typeof result !== 'object' || !result.result || typeof result.result !== 'object') {\n        throw new CommandExecutionError(`${commandLabel} returned an unreadable summary payload`);\n    }\n    const rows = pmids.map((pmid, index) => {\n        const article = result.result[pmid];\n        if (!article) {\n            return null;\n        }\n        return summaryToRow(article, index + 1, pmid);\n    });\n    if (rows.some(row => row === null)) {\n        throw new CommandExecutionError(`${commandLabel} omitted summaries for one or more PMIDs`, 'Refusing to return a partial result set.');\n    }\n    return rows;\n}\n\nexport function buildSearchQuery(query, filters = {}) {\n    const terms = [requireText(query, 'query')];\n    if (filters.author) terms.push(`${requireText(filters.author, 'author')}[Author]`);\n    if (filters.journal) terms.push(`${requireText(filters.journal, 'journal')}[Journal]`);\n    if (filters.yearFrom || filters.yearTo) {\n        const from = filters.yearFrom || 1800;\n        const to = filters.yearTo || new Date().getFullYear();\n        if (from > to) {\n            throw new ArgumentError('pubmed year-from must be <= year-to');\n        }\n        terms.push(`${from}:${to}[PDAT]`);\n    }\n    if (filters.articleType) terms.push(`${requireText(filters.articleType, 'article-type')}[PT]`);\n    if (filters.hasAbstract) terms.push('hasabstract[text]');","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/pubmed/utils.js#L225-L261","documentation":"After mapping PMIDs to summary rows, ensureCompleteSummaryRows checks for null rows (PMIDs with no matching entry in `result.result`) and throws `${commandLabel} omitted summaries for one or more PMIDs` with detail 'Refusing to return a partial result set.' The library throws this rather than silently returning incomplete metadata.","triggerScenarios":"Calling fetchSummaryRows with at least one PMID for which NCBI's ESummary returns no entry — e.g. an invalid/withdrawn/deleted PMID mixed into an otherwise valid batch, or an out-of-range PMID.","commonSituations":"User-supplied PMID lists containing typos or deleted records; PMIDs from a stale saved list; batching PMIDs where one was retracted and removed from ESummary.","solutions":["Validate each PMID before calling (numeric, correct length) and drop invalid ones","Split the batch and query PMIDs individually to identify the offending one","Handle the error by filtering the failing PMID and retrying the rest","Confirm the PMID still exists on pubmed.ncbi.nlm.nih.gov/<pmid>/"],"exampleFix":"// before\nconst rows = await result(['12345678', '99999999999']); // throws\n// after\nconst valid = ['12345678', '99999999999'].filter(p => /^\\d{1,9}$/.test(p));\nconst rows = await result(valid);","handlingStrategy":"validation","validationCode":"// Validate PMIDs before batching\nfunction validPmids(list) {\n  return list.filter(p => /^\\d{1,9}$/.test(String(p)));\n}\nconst pmids = validPmids(userPmids); // drop obviously invalid ones first","typeGuard":"function isPlausiblePmid(p) {\n  return typeof p === 'string' || typeof p === 'number'\n    ? /^\\d{1,9}$/.test(String(p)) : false;\n}","tryCatchPattern":"try {\n  const rows = await result(pmids);\n} catch (e) {\n  if (/omitted summaries/.test(e.message)) {\n    // fall back to per-PMID requests to isolate the bad record\n    const all = await Promise.allSettled(pmids.map(p => result([p])));\n    return all.filter(r => r.status === 'fulfilled').map(r => r.value[0]);\n  }\n  throw e;\n}","preventionTips":["Sanitize PMID lists (numeric only, no whitespace/typos) before batching","Check each PMID resolves on pubmed.ncbi.nlm.nih.gov before including it","Use per-PMID fallback queries to isolate omitted records","Remove PMIDs for retracted/deleted records from stored lists"],"tags":["pubmed","eutils","data-integrity","missing-data"],"backgroundTag":"partial-result-set","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}