jackwener/OpenCLI · error · CommandExecutionError

pubmed article response PMID ${returnedPmid} did not match r

Error message

pubmed article response PMID ${returnedPmid} did not match requested PMID ${pmid}

What it means

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.').

Source

Thrown at clis/pubmed/utils.js:278

    if (filters.articleType) terms.push(`${requireText(filters.articleType, 'article-type')}[PT]`);
    if (filters.hasAbstract) terms.push('hasabstract[text]');
    if (filters.hasFullText) terms.push('free full text[sb]');
    if (filters.humanOnly) terms.push('humans[mesh]');
    if (filters.englishOnly) terms.push('english[lang]');
    return terms.join(' AND ');
}

export function parseArticleXml(xml, pmid) {
    const text = String(xml ?? '');
    if (!text || /<ERROR\b/i.test(text) || !/<PubmedArticle\b/i.test(text)) {
        return null;
    }
    const returnedPmid = extractFirst(text, 'PMID');
    if (!returnedPmid) {
        throw new CommandExecutionError('pubmed article response did not include a PMID', 'PubMed EFetch response shape may have changed.');
    }
    if (returnedPmid !== pmid) {
        throw new CommandExecutionError(`pubmed article response PMID ${returnedPmid} did not match requested PMID ${pmid}`, 'Refusing to return metadata for a different article.');
    }
    const articleBlock = text.match(/<Article\b[^>]*>([\s\S]*?)<\/Article>/i)?.[1] || text;
    const journalBlock = articleBlock.match(/<Journal\b[^>]*>([\s\S]*?)<\/Journal>/i)?.[1] || '';
    const journalIssue = journalBlock.match(/<JournalIssue\b[^>]*>([\s\S]*?)<\/JournalIssue>/i)?.[1] || '';
    const pubDate = journalIssue.match(/<PubDate\b[^>]*>([\s\S]*?)<\/PubDate>/i)?.[1] || '';
    const authorBlocks = [...text.matchAll(/<Author\b[^>]*>([\s\S]*?)<\/Author>/gi)].map(match => match[1]);
    const authors = authorBlocks.map(block => {
        const name = extractFirst(block, 'CollectiveName') || [extractFirst(block, 'LastName'), extractFirst(block, 'ForeName') || extractFirst(block, 'Initials')].filter(Boolean).join(' ');
        return name;
    }).filter(Boolean);
    const abstract = extractAll(articleBlock, 'AbstractText').join(' ');
    const pubTypes = extractAll(articleBlock, 'PublicationType');
    const meshTerms = extractAll(text, 'DescriptorName');
    const keywords = extractAll(text, 'Keyword');
    const affiliations = extractAll(text, 'Affiliation');
    const grantBlocks = [...text.matchAll(/<Grant\b[^>]*>([\s\S]*?)<\/Grant>/gi)].map(match => match[1]);
    const grants = grantBlocks.map(block => {
        const grantId = extractFirst(block, 'GrantID');

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Verify the PMID on pubmed.ncbi.nlm.nih.gov/<pmid>/ — it may have been superseded
  2. Re-run with the canonical PMID PubMed reports after a merge
  3. Clear any caching layer between the CLI and NCBI and retry
  4. Double-check the PMID was not mistyped or swapped in your code

Example fix

// before
await article('31452104'); // cache returned PMIDs for 29868059
// after
cache.clear();
await article('31452104'); // or use the canonical PMID PubMed reports
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the canonical PMID before requesting metadata
const res = await fetch(`https://pubmed.ncbi.nlm.nih.gov/${pmid}/`);
const html = await res.text();
const canonical = /citation_\w*pmid\" content=\"(\d+)\"/.exec(html)?.[1];
if (canonical && canonical !== String(pmid)) {
  pmid = canonical; // PMID was merged/replaced — use the canonical one
}

Type guard

function pmidMatches(responseXml, requested) {
  const m = /<PMID\b[^>]*>([^<]+)<\/PMID>/i.exec(String(responseXml));
  return Boolean(m) && m[1].trim() === String(requested);
}

Try / catch

try {
  const meta = await article(pmid);
} catch (e) {
  const m = /PMID (\d+) did not match requested PMID (\d+)/.exec(e.message);
  if (m) return article(m[1]); // retry with the PMID the server actually returned
  throw e;
}

Prevention

When it happens

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

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

Related errors


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