jackwener/OpenCLI · warning · ArgumentError

pubmed year-from must be <= year-to

Error message

pubmed year-from must be <= year-to

What it means

ArgumentError thrown at clis/pubmed/author.js:45 during query construction when the user-supplied year-from is greater than year-to. The command builds a PDAT date-range term (`${from}:${to}[PDAT]`) for the PubMed esearch query and rejects impossible ranges before any network call is made. This is pure client-side input validation.

Source

Thrown at clis/pubmed/author.js:45

        { name: 'year-to', type: 'int', help: 'Filter publication year to' },
        { name: 'sort', default: 'date', choices: ['date', 'relevance'], help: 'Sort by date or relevance' },
    ],
    columns: LINK_COLUMNS,
    func: async (args) => {
        const name = requireText(args.name, 'author');
        const limit = requireBoundedInt(args.limit, 20, 100);
        const position = requireChoice(args.position, ['any', 'first', 'last'], 'position', 'any');
        const sort = requireChoice(args.sort, ['date', 'relevance'], 'sort', 'date');
        const yearFrom = requireYear(args['year-from'], 'year-from');
        const yearTo = requireYear(args['year-to'], 'year-to');
        const authorTag = position === 'first' ? '1au' : position === 'last' ? 'lastau' : 'au';
        const terms = [`${name}[${authorTag}]`];
        if (args.affiliation) terms.push(`${requireText(args.affiliation, 'affiliation')}[ad]`);
        if (yearFrom || yearTo) {
            const from = yearFrom || 1800;
            const to = yearTo || new Date().getFullYear();
            if (from > to) {
                throw new ArgumentError('pubmed year-from must be <= year-to');
            }
            terms.push(`${from}:${to}[PDAT]`);
        }
        const esearch = await eutilsFetch('esearch', {
            term: terms.join(' AND '),
            retmax: limit,
            usehistory: 'y',
            sort: sort === 'date' ? 'pub_date' : '',
        }, { label: 'pubmed author' });
        const pmids = esearch?.esearchresult?.idlist;
        if (!Array.isArray(pmids)) {
            throw new CommandExecutionError('pubmed author did not return an id list', 'PubMed ESearch response shape may have changed.');
        }
        if (pmids.length === 0) {
            throw new EmptyResultError('pubmed author', `No articles found for author "${name}".`);
        }
        return fetchSummaryRows(pmids, 'pubmed author summary');
    },

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Swap the values so year-from <= year-to before invoking the command
  2. Validate the two year args at the CLI/app level before calling pubmed author
  3. If computed dynamically, clamp or sort from/to before passing them
  4. Check flag names/order in your script — you may have assigned year-to to year-from

Example fix

// before
const args = { 'year-from': '2023', 'year-to': '2020' };
await runCli('pubmed author "Jane Doe"', args);
// after
const args = { 'year-from': '2020', 'year-to': '2023' };
if (Number(args['year-from']) > Number(args['year-to'])) {
    throw new Error('year-from must be <= year-to');
}
await runCli('pubmed author "Jane Doe"', args);
Defensive patterns

Strategy: validation

Validate before calling

// guard the year range before invoking the command
const from = Number(opts['year-from']);
const to = Number(opts['year-to']);
if (from > to) {
  [opts['year-from'], opts['year-to']] = [opts['year-to'], opts['year-from']]; // or reject
}

Type guard

function isValidYearRange(from, to) {
  return Number.isInteger(from) && Number.isInteger(to) && from <= to;
}

Try / catch

try {
  const rows = await runCli('pubmed author', authorArgs);
} catch (e) {
  if (e instanceof ArgumentError || /year-from must be <= year-to/.test(e.message)) {
    console.error('Bad year range: swap year-from and year-to and retry.');
    process.exitCode = 2;
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling `pubmed author <name> --year-from 2023 --year-to 2020` (or equivalent args object {yearFrom: 2023, yearTo: 2020}); defaults fill missing values (from=1800, to=current year) so an explicitly bad pair is required to trigger it.

Common situations: Swapping the two flags by mistake; scripting calls where yearFrom/yearTo are computed dynamically and inverted (e.g. relative year offsets); copy-paste from an example with reversed order; user misunderstanding that year-from is the earlier bound.

Related errors


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