jackwener/OpenCLI · error · ArgumentError

limit must be a positive integer

Error message

limit must be a positive integer

What it means

The followers command validates its --limit option before doing any work: it must be an integer greater than 0 (Number.isInteger(limit) && limit > 0). Note the CLI declares type 'int' with default 50, so this error means the value supplied programmatically via kwargs.limit (or a non-integer/fractional CLI value) failed validation. It is an ArgumentError raised immediately, before any browser session or network activity.

Source

Thrown at clis/twitter/followers.js:96

    browser: true,
    args: [
        {
            name: 'user',
            positional: true,
            type: 'string',
            required: false,
            help: 'Twitter/X handle (with or without @). Omit to fetch followers of the currently logged-in account.',
        },
        { name: 'limit', type: 'int', default: 50, help: 'Maximum number of follower rows to return (default 50). Must be a positive integer.' },
    ],
    // Preserve the historical three-column contract even though the GraphQL
    // payload also contains per-user relationship counts. Use `twitter profile`
    // when a dedicated follower count is needed.
    columns: ['screen_name', 'name', 'bio'],
    func: async (page, kwargs) => {
        const limit = kwargs.limit;
        if (!Number.isInteger(limit) || limit <= 0) {
            throw new ArgumentError('limit must be a positive integer');
        }

        const rawUser = String(kwargs.user ?? '').trim();
        let targetUser = normalizeScreenName(rawUser);
        if (rawUser && !targetUser) {
            throw new ArgumentError('twitter followers user must be a valid Twitter/X handle', 'Example: opencli twitter followers @elonmusk --limit 100');
        }
        await page.goto('https://x.com/home');
        await page.wait({ selector: '[data-testid="primaryColumn"]' });
        const cookies = await page.getCookies({ url: 'https://x.com' });
        const ct0 = cookies.find((cookie) => cookie.name === 'ct0')?.value || null;
        if (!ct0) {
            throw new AuthRequiredError('x.com', 'Not logged into x.com (no ct0 cookie)');
        }

        if (!targetUser) {
            // Bridge wraps primitive page.evaluate returns as { session, data:<value> };
            // unwrap so the href string is usable downstream.

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass limit as a positive integer, e.g. --limit 100
  2. Coerce and validate before calling: const limit = Math.floor(Number(raw)); if (!Number.isInteger(limit) || limit <= 0) ...
  3. Omit the option to use the default of 50

Example fix

// before
opencli twitter followers @elonmusk --limit 0
// after
opencli twitter followers @elonmusk --limit 100
Defensive patterns

Strategy: validation

Validate before calling

function assertLimit(n) {
  const v = Math.floor(Number(n));
  if (!Number.isInteger(v) || v <= 0) throw new Error('limit must be a positive integer');
  return v;
}
const limit = assertLimit(process.env.LIMIT ?? 50);

Type guard

const isPositiveInt = (v) => Number.isInteger(v) && v > 0;

Try / catch

try {
  await opencli.twitter.followers(user, { limit });
} catch (err) {
  if (err.message === 'limit must be a positive integer') {
    limit = 50; // fall back to default
  } else throw err;
}

Prevention

When it happens

Trigger: Calling the command's func with kwargs.limit set to 0, a negative number, NaN, Infinity, a float like 2.5, or a numeric string like '100' instead of a number.

Common situations: Passing a string from a config file or environment variable instead of a parsed int; computing the limit with arithmetic that yields a float; forgetting the default and passing undefined from a wrapper.

Related errors


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