jackwener/OpenCLI · error · ArgumentError

huodongxing limit must be a positive integer

Error message

huodongxing limit must be a positive integer

What it means

requireLimit normalizes the huodongxing events `limit` option (default 20) into a positive integer. It throws this ArgumentError when the value is not an integer or is <= 0 — e.g. non-numeric strings, floats, zero, negatives, or NaN from unparsable text. This validates input before it reaches the scraper's pagination logic.

Source

Thrown at clis/huodongxing/events.js:27

  'id',
  'title',
  'time',
  'eventType',
  'city',
  'location',
  'organizer',
  'url',
];

function cleanText(value) {
  return String(value ?? '').replace(/\s+/g, ' ').trim();
}

export function requireLimit(value) {
  const raw = value ?? 20;
  const limit = typeof raw === 'number' ? raw : Number(String(raw).trim());
  if (!Number.isInteger(limit) || limit <= 0) {
    throw new ArgumentError('huodongxing limit must be a positive integer');
  }
  if (limit > MAX_LIMIT) {
    throw new ArgumentError(`huodongxing limit must be <= ${MAX_LIMIT}`);
  }
  return limit;
}

function appendIfPresent(params, name, value) {
  const text = cleanText(value);
  if (text) params.set(name, text);
}

function dateOrdinal(year, month, day) {
  return Math.floor(Date.UTC(year, month - 1, day) / 86400000);
}

function parseYmd(value) {
  const match = cleanText(value).match(/^(\d{4})-(\d{2})-(\d{2})$/);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a positive integer (1–50): limit(10) or limit('10') both work since strings are coerced via Number().
  2. Validate/coerce the option at the call site: Number.parseInt(value, 10) and check Number.isInteger before calling.
  3. Replace 0/negative values meant as 'all' with the maximum (50) or omit the option to use the default 20.

Example fix

// before
await events({ limit: 'ten' });   // ArgumentError
await events({ limit: 0 });       // ArgumentError
// after
const n = Number.parseInt(userLimit, 10);
await events({ limit: Number.isInteger(n) && n > 0 ? n : 20 });
Defensive patterns

Strategy: validation

Validate before calling

function parseLimit(value, { max = 50, def = 20 } = {}) {
  const n = typeof value === 'number' ? value : Number(String(value ?? '').trim());
  return Number.isInteger(n) && n > 0 ? n : def;
}
const limit = parseLimit(userInput);

Type guard

function isPositiveInt(v) {
  return typeof v === 'number' && Number.isInteger(v) && v > 0;
}

Try / catch

try {
  await events({ limit });
} catch (err) {
  if (err instanceof ArgumentError && err.message.includes('limit must be a positive integer')) {
    await events({ limit: 20 }); // fall back to default
  } else throw err;
}

Prevention

When it happens

Trigger: limit('abc'), limit(0), limit(-5), limit(2.5), limit(''), limit(undefined as 'undefined') — any call path where the limit option is a string/number failing Number.isInteger && > 0. Note the error message says 'positive integer' but the code also rejects NaN produced by Number('abc').

Common situations: CLI flag parsing delivering strings like 'ten' or '1..5'; config files with quoted or empty values; users passing 0 expecting 'unlimited'; float math upstream (e.g. items.length/2) leaking into limit.

Related errors


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