{"record":{"id":"9dd9cfebb380bec9","repo":"jackwener/OpenCLI","slug":"pubmed-article-response-pmid-returnedpmid-did-n","errorCode":null,"errorMessage":"pubmed article response PMID ${returnedPmid} did not match requested PMID ${pmid}","messagePattern":"pubmed article response PMID (.+?) did not match requested PMID (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/pubmed/utils.js","lineNumber":278,"sourceCode":"    if (filters.articleType) terms.push(`${requireText(filters.articleType, 'article-type')}[PT]`);\n    if (filters.hasAbstract) terms.push('hasabstract[text]');\n    if (filters.hasFullText) terms.push('free full text[sb]');\n    if (filters.humanOnly) terms.push('humans[mesh]');\n    if (filters.englishOnly) terms.push('english[lang]');\n    return terms.join(' AND ');\n}\n\nexport function parseArticleXml(xml, pmid) {\n    const text = String(xml ?? '');\n    if (!text || /<ERROR\\b/i.test(text) || !/<PubmedArticle\\b/i.test(text)) {\n        return null;\n    }\n    const returnedPmid = extractFirst(text, 'PMID');\n    if (!returnedPmid) {\n        throw new CommandExecutionError('pubmed article response did not include a PMID', 'PubMed EFetch response shape may have changed.');\n    }\n    if (returnedPmid !== pmid) {\n        throw new CommandExecutionError(`pubmed article response PMID ${returnedPmid} did not match requested PMID ${pmid}`, 'Refusing to return metadata for a different article.');\n    }\n    const articleBlock = text.match(/<Article\\b[^>]*>([\\s\\S]*?)<\\/Article>/i)?.[1] || text;\n    const journalBlock = articleBlock.match(/<Journal\\b[^>]*>([\\s\\S]*?)<\\/Journal>/i)?.[1] || '';\n    const journalIssue = journalBlock.match(/<JournalIssue\\b[^>]*>([\\s\\S]*?)<\\/JournalIssue>/i)?.[1] || '';\n    const pubDate = journalIssue.match(/<PubDate\\b[^>]*>([\\s\\S]*?)<\\/PubDate>/i)?.[1] || '';\n    const authorBlocks = [...text.matchAll(/<Author\\b[^>]*>([\\s\\S]*?)<\\/Author>/gi)].map(match => match[1]);\n    const authors = authorBlocks.map(block => {\n        const name = extractFirst(block, 'CollectiveName') || [extractFirst(block, 'LastName'), extractFirst(block, 'ForeName') || extractFirst(block, 'Initials')].filter(Boolean).join(' ');\n        return name;\n    }).filter(Boolean);\n    const abstract = extractAll(articleBlock, 'AbstractText').join(' ');\n    const pubTypes = extractAll(articleBlock, 'PublicationType');\n    const meshTerms = extractAll(text, 'DescriptorName');\n    const keywords = extractAll(text, 'Keyword');\n    const affiliations = extractAll(text, 'Affiliation');\n    const grantBlocks = [...text.matchAll(/<Grant\\b[^>]*>([\\s\\S]*?)<\\/Grant>/gi)].map(match => match[1]);\n    const grants = grantBlocks.map(block => {\n        const grantId = extractFirst(block, 'GrantID');","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/pubmed/utils.js#L260-L296","documentation":"parseArticleXml compares the PMID found in the EFetch XML against the requested PMID and throws `pubmed article response PMID ${returnedPmid} did not match requested PMID ${pmid}` on mismatch. This guards against returning metadata for a different article than the user asked for (detail: 'Refusing to return metadata for a different article.').","triggerScenarios":"Calling the article command with a PMID when NCBI returns an article record for a different identifier — e.g. the PMID was merged/replaced and NCBI substituted the canonical record, or a caching/proxy layer returned a stale response for another PMID.","commonSituations":"PubMed PMID merges after journal changes; using a wrong or mistyped PMID that maps to another record; CDN or local cache serving the wrong response; requesting via a secondary ID (DOI/PMC) resolved to a different PMID.","solutions":["Verify the PMID on pubmed.ncbi.nlm.nih.gov/<pmid>/ — it may have been superseded","Re-run with the canonical PMID PubMed reports after a merge","Clear any caching layer between the CLI and NCBI and retry","Double-check the PMID was not mistyped or swapped in your code"],"exampleFix":"// before\nawait article('31452104'); // cache returned PMIDs for 29868059\n// after\ncache.clear();\nawait article('31452104'); // or use the canonical PMID PubMed reports","handlingStrategy":"validation","validationCode":"// Confirm the canonical PMID before requesting metadata\nconst res = await fetch(`https://pubmed.ncbi.nlm.nih.gov/${pmid}/`);\nconst html = await res.text();\nconst canonical = /citation_\\w*pmid\\\" content=\\\"(\\d+)\\\"/.exec(html)?.[1];\nif (canonical && canonical !== String(pmid)) {\n  pmid = canonical; // PMID was merged/replaced — use the canonical one\n}","typeGuard":"function pmidMatches(responseXml, requested) {\n  const m = /<PMID\\b[^>]*>([^<]+)<\\/PMID>/i.exec(String(responseXml));\n  return Boolean(m) && m[1].trim() === String(requested);\n}","tryCatchPattern":"try {\n  const meta = await article(pmid);\n} catch (e) {\n  const m = /PMID (\\d+) did not match requested PMID (\\d+)/.exec(e.message);\n  if (m) return article(m[1]); // retry with the PMID the server actually returned\n  throw e;\n}","preventionTips":["Resolve PMIDs through PubMed's canonical lookup; handle merged records","Avoid caching EFetch responses keyed loosely — key strictly by PMID","Double-check PMIDs for typos before requesting","Log both requested and returned PMIDs when this error occurs"],"tags":["pubmed","efetch","data-integrity","pmid-mismatch"],"backgroundTag":"response-id-mismatch","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}