{"record":{"id":"bfbef0889b9e01dc","repo":"jackwener/OpenCLI","slug":"pubmed-article-response-did-not-include-a-pmid","errorCode":null,"errorMessage":"pubmed article response did not include a PMID","messagePattern":"pubmed article response did not include a PMID","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/pubmed/utils.js","lineNumber":275,"sourceCode":"        }\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]');\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');","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/pubmed/utils.js#L257-L293","documentation":"parseArticleXml extracts the PMID from the EFetch XML response and throws 'pubmed article response did not include a PMID' when no <PMID> element can be found, even though the body looked like a PubmedArticle. The library throws this because without the returned PMID it cannot verify the response corresponds to the requested article.","triggerScenarios":"Calling the article command when NCBI's EFetch returns a PubmedArticle-shaped document with no <PMID> tag inside — typically due to an NCBI response format change, a heavily truncated/garbled XML body, or XML where the PMID tag is namespaced/renamed.","commonSituations":"NCBI schema updates altering tag placement; proxies mangling XML; NCBI returning an unusual article encoding (e.g. PMC-sourced records without PMID).","solutions":["Retry the request — a transient truncation can drop elements","Inspect the raw XML to confirm whether <PMID> is genuinely absent","Check for NCBI DTD/schema updates and update the parser if tags changed","Fall back to fetching metadata from the PubMed web page instead of EFetch"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-flight: confirm the article exists before parsing\nconst res = await fetch(`https://pubmed.ncbi.nlm.nih.gov/${pmid}/`);\nif (!res.ok) throw new Error(`PMID ${pmid} not found on PubMed`);","typeGuard":"function hasPmidElement(xmlText) {\n  return /<PMID\\b[^>]*>[^<]+<\\/PMID>/i.test(String(xmlText));\n}","tryCatchPattern":"try {\n  const meta = await article(pmid);\n} catch (e) {\n  if (/did not include a PMID/.test(e.message)) {\n    console.error('EFetch XML had no <PMID>; inspect raw response:', e.detail);\n  }\n  throw e;\n}","preventionTips":["Log raw EFetch XML on failure to detect schema/truncation issues","Pin and monitor NCBI DTD/schema versions for changes","Retry once on parse failures — truncation can be transient","Keep a fallback path (PubMed web scrape / other API) for metadata"],"tags":["pubmed","efetch","xml-parsing","schema-mismatch"],"backgroundTag":"unexpected-response-schema","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}