jackwener/OpenCLI · error · ArgumentError

coingecko limit must be a positive integer

Error message

coingecko limit must be a positive integer

What it means

ArgumentError thrown by the coingecko exchanges command when the --limit argument is not a positive integer (Number() coercion fails, is fractional, NaN, or <= 0). The library validates arguments up-front so the API call is never made with an invalid per_page.

Source

Thrown at clis/coingecko/exchanges.js:25

import { ArgumentError, CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';

cli({
    site: 'coingecko',
    name: 'exchanges',
    access: 'read',
    description: 'Top crypto exchanges by 24h BTC trading volume',
    domain: 'api.coingecko.com',
    strategy: Strategy.PUBLIC,
    browser: false,
    args: [
        { name: 'limit', type: 'int', default: 20, help: 'Number of exchanges (1-250, CoinGecko per_page upper bound)' },
        { name: 'page', type: 'int', default: 1, help: 'Page number (1-based)' },
    ],
    columns: ['rank', 'id', 'name', 'trustScore', 'volume24hBtc', 'country', 'yearEstablished', 'url'],
    func: async (args) => {
        const limit = Number(args.limit ?? 20);
        if (!Number.isInteger(limit) || limit <= 0) {
            throw new ArgumentError('coingecko limit must be a positive integer');
        }
        if (limit > 250) {
            throw new ArgumentError('coingecko limit must be <= 250 (per_page upper bound)');
        }
        const page = Number(args.page ?? 1);
        if (!Number.isInteger(page) || page <= 0) {
            throw new ArgumentError('coingecko page must be a positive integer');
        }
        const url = new URL('https://api.coingecko.com/api/v3/exchanges');
        url.searchParams.set('per_page', String(limit));
        url.searchParams.set('page', String(page));
        let resp;
        try {
            resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0' } });
        }
        catch (err) {
            throw new CommandExecutionError(`coingecko exchanges request failed: ${err?.message ?? err}`);
        }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a whole number >= 1, e.g. --limit 20.
  2. If the value comes from a script/config, coerce and validate with Number.isInteger(Number(v)) && Number(v) > 0 before invoking.
  3. Check shell quoting so the flag isn't empty or split.
  4. Omit --limit entirely to use the default of 20.

Example fix

// before
runCli(['coingecko', 'exchanges', '--limit', 'all']);
// after
const limit = 100;
runCli(['coingecko', 'exchanges', '--limit', String(limit)]);
Defensive patterns

Strategy: validation

Validate before calling

const n = Number(limit);
if (!Number.isInteger(n) || n <= 0) {
  throw new TypeError(`limit must be a positive integer, got ${JSON.stringify(limit)}`);
}

Type guard

function isValidLimit(v) {
  const n = Number(v);
  return Number.isInteger(n) && n > 0 && n <= 250;
}

Try / catch

try {
  return await runCli(['coingecko', 'exchanges', '--limit', String(limit)]);
} catch (err) {
  if (String(err.message).includes('limit must be a positive integer')) {
    console.warn(`Invalid limit "${limit}"; falling back to default 20.`);
    return runCli(['coingecko', 'exchanges']);
  }
  throw err;
}

Prevention

When it happens

Trigger: Passing --limit 0, --limit -5, --limit abc, --limit 2.5, or an empty string that coerces to NaN when running the exchanges command.

Common situations: Shell quoting mistakes (empty --limit ''), copy-pasted fractional values, scripts computing a limit with parseFloat on non-numeric input, default omitted and a placeholder left in a config.

Related errors


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