jackwener/OpenCLI · warning · ArgumentError
--limit must be a positive integer, got ${JSON.stringify(raw
Error message
--limit must be a positive integer, got ${JSON.stringify(raw)} What it means
parseLimit coerces the raw --limit CLI value with Number() and requires a finite integer. Non-numeric or non-integer input (e.g. 'abc', 2.5, '') throws ArgumentError with the JSON-stringified raw value.
Source
Thrown at clis/xiaohongshu/feed.js:22
* Earlier versions used a `tap` step that called the `fetchFeeds` store action,
* which fetches the NEXT page of recommendations. Those API items carry no
* `xsecToken` and do not overlap the first-screen notes, so the feed's URLs
* could not be passed to `note`/`comments`/`download` (which require a signed
* URL). The hydrated store, by contrast, holds `entry.xsecToken` for every
* first-screen note, so a func-mode read yields signed, drill-down-ready URLs.
*
* Mirrors rednote/feed.js: the hydrated store is camelCase on both sites
* (`noteCard.displayTitle`, `interactInfo.likedCount`). This is the SSR store
* shape, not the snake_case `/homefeed` API response the old tap intercepted.
*/
import { cli, Strategy } from '@jackwener/opencli/registry';
import { ArgumentError, CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';
import { unwrapEvaluateResult } from './shared.js';
function parseLimit(raw) {
const parsed = Number(raw ?? 20);
if (!Number.isFinite(parsed) || !Number.isInteger(parsed)) {
throw new ArgumentError(`--limit must be a positive integer, got ${JSON.stringify(raw)}`);
}
if (parsed < 1) {
throw new ArgumentError(`--limit must be a positive integer, got ${parsed}`);
}
return parsed;
}
const FEEDS_READ_JS = `
(() => {
let pinia = null;
const probe = (el) => el?.__vue_app__?.config?.globalProperties?.$pinia ?? null;
pinia = probe(document.querySelector('#app'));
if (!pinia) {
// Some builds mount under a different root id; fall back to a full scan
// only when the standard mount node misses.
for (const el of document.querySelectorAll('*')) {
pinia = probe(el);
if (pinia) break;View on GitHub (pinned to 49907e53dc)
Solutions
- Pass a positive integer: --limit 20
- If the value comes from a script/env var, ensure it is a non-empty integer string
- Omit --limit entirely to use the default of 20
- Trim whitespace/newlines from the value before passing
Example fix
// before xhs feed --limit 2.5 // after xhs feed --limit 25
Defensive patterns
Strategy: validation
Validate before calling
const n = Number(raw);
if (raw != null && (!Number.isFinite(n) || !Number.isInteger(n))) throw new Error(`--limit must be an integer, got ${raw}`); Type guard
function isValidLimit(raw) { if (raw == null) return true; const n = Number(raw); return Number.isInteger(n); } Try / catch
try {
await cli.feed({ limit: rawLimit });
} catch (err) {
if (err instanceof ArgumentError && err.message.startsWith('--limit')) {
console.error('Usage: --limit <positive integer>');
} else throw err;
} Prevention
- Pass integer strings for --limit; avoid floats and words
- Trim shell variables before interpolation
- Omit --limit to use the default 20
- Validate CLI args in wrapper scripts before invoking
When it happens
Trigger: Calling the feed command with --limit set to a non-integer or non-numeric string, e.g. --limit=abc, --limit=2.5, --limit=''. Note null/undefined are allowed (defaults to 20).
Common situations: Shell quoting issues passing '20\n', users passing floats or words, scripts interpolating empty variables into --limit, config files supplying "all" instead of a number.
Related errors
- <train-no> "${trainNo}" does not look like a 12306 internal
- --from station must not be empty
- --to station must not be empty
- --seat-types must contain only 12306 seat letters/digits (A-
- --from and --to must differ; both resolved to ${fromStation.
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/c5ba277be75b944c.
Report an issue: GitHub.