jackwener/OpenCLI · error · ArgumentError

'limit', 'must be a positive integer ≤ 200'

Error message

'limit', 'must be a positive integer ≤ 200'

What it means

The gemini history command validates its --limit option and throws ArgumentError('limit', 'must be a positive integer ≤ 200') when the value is not an integer in [1, 200]. The bound prevents requesting unbounded sidebar scraping, since only a limited Recents list exists. Note that default 20 is passed through Number(), so numeric strings like '25' are accepted but non-numeric strings are not.

Source

Thrown at clis/gemini/history.js:45

export const historyCommand = cli({
    site: 'gemini',
    name: 'history',
    access: 'read',
    description: 'List visible Gemini web conversation history from the sidebar',
    domain: GEMINI_DOMAIN,
    strategy: Strategy.COOKIE,
    browser: true,
    siteSession: 'persistent',
    navigateBefore: false,
    args: [
        { name: 'limit', type: 'int', default: 20, help: 'Max conversations to show' },
    ],
    columns: ['Index', 'Id', 'Title', 'Url'],
    func: async (page, kwargs) => {
        const rawLimit = Number(kwargs?.limit ?? 20);
        if (!Number.isInteger(rawLimit) || rawLimit < 1 || rawLimit > 200) {
            throw new ArgumentError('limit', 'must be a positive integer ≤ 200');
        }
        await ensureGeminiPage(page);
        const conversations = await getGeminiConversationList(page);
        if (!conversations.length) {
            throw new EmptyResultError(
                'gemini history',
                'No Gemini conversation links were visible in the sidebar. Open the sidebar and confirm at least one chat is listed under Recents.',
            );
        }
        // The sidebar mixes a "New chat" affordance (URL = /app, no id) into
        // the same link list; drop entries that don't resolve to a real
        // conversation id so callers get a clean conversation list.
        const rows = conversations
            .map((row) => ({ id: extractGeminiId(row.Url), title: row.Title || '', url: row.Url || '' }))
            .filter((row) => row.id);
        return rows.slice(0, rawLimit).map((row, idx) => ({
            Index: idx + 1,
            Id: row.id,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Use an integer between 1 and 200, e.g. --limit 50
  2. Replace 'all' or other words with a concrete number (max useful is 200)
  3. Round computed values with Math.round/Math.floor before passing
  4. If you need more conversations than the limit, note the sidebar itself only exposes a bounded Recents list

Example fix

// before
opencli gemini history --limit all
// after
opencli gemini history --limit 200
Defensive patterns

Strategy: validation

Validate before calling

const limit = Math.round(Number(rawLimit ?? 20));
if (!(limit >= 1 && limit <= 200)) throw new Error('limit must be an integer in [1, 200]');

Type guard

const isValidLimit = (v) => Number.isInteger(v) && v >= 1 && v <= 200;

Try / catch

try {
  return await run(['gemini','history','--limit', String(limit)]);
} catch (e) {
  if (String(e.message).includes('positive integer ≤ 200')) {
    return await run(['gemini','history','--limit','20']); // safe default
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling `opencli gemini history` with --limit 0, negative, > 200, fractional (10.5), or a non-numeric string like 'all' or 'twenty'.

Common situations: Passing --limit all to try to see everything; a wrapper computing a limit from a ratio producing a float; typo like --limit 2000; shell variable expanding to empty so NaN results from Number(undefined ?? 20) misuse when kwarg is explicitly empty string.

Understand the failure class

Background: "Unknown argument", "Invalid value", and "must be one of": invalid CLI argument errors explained — this error's family across 35 libraries.

Related errors


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