jackwener/OpenCLI · error · ArgumentError

pubmed year-from must be <= year-to

Error message

pubmed year-from must be <= year-to

What it means

buildSearchQuery validates the optional year range filters before constructing the PubMed PDAT date-range term. If filters.yearFrom exceeds filters.yearTo it throws ArgumentError 'pubmed year-from must be <= year-to'. The library throws this up front because an inverted range would silently produce an empty/meaningless query.

Source

Thrown at clis/pubmed/utils.js:256

            return null;
        }
        return summaryToRow(article, index + 1, pmid);
    });
    if (rows.some(row => row === null)) {
        throw new CommandExecutionError(`${commandLabel} omitted summaries for one or more PMIDs`, 'Refusing to return a partial result set.');
    }
    return rows;
}

export function buildSearchQuery(query, filters = {}) {
    const terms = [requireText(query, 'query')];
    if (filters.author) terms.push(`${requireText(filters.author, 'author')}[Author]`);
    if (filters.journal) terms.push(`${requireText(filters.journal, 'journal')}[Journal]`);
    if (filters.yearFrom || filters.yearTo) {
        const from = filters.yearFrom || 1800;
        const to = filters.yearTo || new Date().getFullYear();
        if (from > to) {
            throw new ArgumentError('pubmed year-from must be <= year-to');
        }
        terms.push(`${from}:${to}[PDAT]`);
    }
    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) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Swap the values so yearFrom <= yearTo in the caller
  2. Validate the range before invoking: if (from > to) swap or reject
  3. Check for argument-order mistakes where the filter object was constructed

Example fix

// before
await searchQuery(q, { yearFrom: 2024, yearTo: 2020 });
// after
const from = Math.min(2024, 2020), to = Math.max(2024, 2020);
await searchQuery(q, { yearFrom: from, yearTo: to });
Defensive patterns

Strategy: validation

Validate before calling

// Validate the year range before calling searchQuery
function checkYearRange(filters) {
  const from = filters.yearFrom ?? 1800;
  const to = filters.yearTo ?? new Date().getFullYear();
  if (from > to) throw new Error('yearFrom must be <= yearTo');
}
checkYearRange({ yearFrom: 2024, yearTo: 2020 }); // throws early

Try / catch

try {
  const q = await searchQuery(query, filters);
} catch (e) {
  if (/year-from must be <= year-to/.test(e.message)) {
    [filters.yearFrom, filters.yearTo] = [filters.yearTo, filters.yearFrom];
    return searchQuery(query, filters); // auto-correct and retry
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling searchQuery (or any search entry point) with filters like { yearFrom: 2024, yearTo: 2020 } — from greater than to. Defaults apply when only one bound is given (from defaults to 1800, to defaults to current year), so the error only fires when both are explicitly set and inverted.

Common situations: Swapping the from/to arguments by mistake; UI or script passing dates in the wrong order; programmatically building ranges where variables got mixed up.

Related errors


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