{"record":{"id":"02d692a88b1e50a6","repo":"jackwener/OpenCLI","slug":"pubmed-label-must-be-a-numeric-pmid","errorCode":null,"errorMessage":"pubmed ${label} must be a numeric PMID","messagePattern":"pubmed (.+?) must be a numeric PMID","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/pubmed/utils.js","lineNumber":21,"sourceCode":"export const EUTILS_BASE = 'https://eutils.ncbi.nlm.nih.gov/entrez/eutils';\nexport const SEARCH_COLUMNS = ['rank', 'pmid', 'title', 'authors', 'journal', 'year', 'article_type', 'doi', 'url'];\nexport const LINK_COLUMNS = ['rank', 'pmid', 'title', 'authors', 'journal', 'year', 'article_type', 'doi', 'url'];\nexport const RELATED_COLUMNS = ['rank', 'pmid', 'title', 'authors', 'journal', 'year', 'article_type', 'score', 'doi', 'url'];\n\nlet lastRequestAt = 0;\n\nexport function requireText(value, label) {\n    const text = String(value ?? '').trim();\n    if (!text) {\n        throw new ArgumentError(`pubmed ${label} cannot be empty`);\n    }\n    return text;\n}\n\nexport function requirePmid(value, label = 'pmid') {\n    const pmid = requireText(value, label);\n    if (!/^\\d+$/.test(pmid)) {\n        throw new ArgumentError(`pubmed ${label} must be a numeric PMID`, 'Example: 37780221');\n    }\n    return pmid;\n}\n\nexport function requireBoundedInt(value, defaultValue, maxValue, label = 'limit') {\n    const raw = value ?? defaultValue;\n    const text = String(raw).trim();\n    if (!/^\\d+$/.test(text)) {\n        throw new ArgumentError(`pubmed ${label} must be a positive integer`);\n    }\n    const n = Number(text);\n    if (!Number.isSafeInteger(n) || n < 1) {\n        throw new ArgumentError(`pubmed ${label} must be a positive integer`);\n    }\n    if (n > maxValue) {\n        throw new ArgumentError(`pubmed ${label} must be <= ${maxValue}`);\n    }\n    return n;","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/pubmed/utils.js#L3-L39","documentation":"requirePmid validates that the input is a bare numeric PubMed ID. Non-numeric values throw ArgumentError 'pubmed <label> must be a numeric PMID' with the example '37780221', catching DOIs, PMCIDs, titles, and multi-ID pastes before an NCBI call.","triggerScenarios":"Calling `pubmed pmid <value>` with '10.1038/...' (DOI), 'PMC1234567', an article title, or '123 456' (multiple IDs).","commonSituations":"Confusing PMCID with PMID, pasting a DOI where a PMID is expected, passing a search query instead of a resolved ID.","solutions":["Pass a pure digit PMID, e.g. 37780221","Run `pubmed search` first to resolve a title/DOI/query to a PMID, then use that ID","Strip surrounding text/whitespace; do not add an 'PMC' prefix"],"exampleFix":"// before\nawait pubmedPmid('10.1038/s41586-023-06600-9');\n// after\nconst rows = await pubmedSearch('10.1038/s41586-023-06600-9');\nawait pubmedPmid(rows[0].pmid); // e.g. '37780221'","handlingStrategy":"validation","validationCode":"if (!/^\\d+$/.test(String(pmid ?? '').trim())) {\n  throw new Error(`'${pmid}' is not a numeric PMID (example: 37780221)`);\n}","typeGuard":"function isPmid(v) {\n  return typeof v === 'string' || typeof v === 'number'\n    ? /^\\d+$/.test(String(v).trim())\n    : false;\n}","tryCatchPattern":"try {\n  await pubmedPmid(input);\n} catch (err) {\n  if (err instanceof ArgumentError && /numeric PMID/.test(err.message)) {\n    const resolved = await pubmedSearch(input); // resolve DOI/title to PMID\n    await pubmedPmid(resolved[0].pmid);\n  } else { throw err; }\n}","preventionTips":["Do not confuse PMID (digits) with PMCID (PMC prefix) or DOI","Resolve titles/DOIs via `pubmed search` before calling ID-based commands","Paste IDs without surrounding text or multiple IDs"],"tags":["validation","argument-error","pmid","pubmed"],"backgroundTag":"invalid-identifier-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}