jackwener/OpenCLI · error · ArgumentError
budgetMs must be a positive number, got ${JSON.stringify(bud
Error message
budgetMs must be a positive number, got ${JSON.stringify(budgetMs)} What it means
buildScrollHarvestJs validates budgetMs as a finite number > 0 (default 30_000 via options.budgetMs) and throws this ArgumentError otherwise. budgetMs is the wall-clock time budget injected into the harvest script, so a zero, negative, or non-finite value would make the time-loop logic nonsensical and is rejected at build time.
Source
Thrown at clis/xiaohongshu/search.js:634
const stripXhsAuthorDateSuffix = ${stripXhsAuthorDateSuffix.toString()};
const extractSearchRows = ${extractSearchRows.toString()};
return extractSearchRows(${JSON.stringify(webHost)});
})()
`;
}
export function buildScrollHarvestJs(webHost, targetCount, options = {}) {
const maxRounds = options.maxRounds ?? 30;
const budgetMs = options.budgetMs ?? 30_000;
const step = options.step ?? DEFAULT_HARVEST_STEP;
if (!Number.isSafeInteger(targetCount) || targetCount < 1) {
throw new ArgumentError(`targetCount must be a positive integer, got ${JSON.stringify(targetCount)}`);
}
if (!Number.isSafeInteger(maxRounds) || maxRounds < 1) {
throw new ArgumentError(`maxRounds must be a positive integer, got ${JSON.stringify(maxRounds)}`);
}
if (!Number.isFinite(budgetMs) || budgetMs <= 0) {
throw new ArgumentError(`budgetMs must be a positive number, got ${JSON.stringify(budgetMs)}`);
}
if (!Number.isFinite(step) || step < 0) {
throw new ArgumentError(`step must be a non-negative number, got ${JSON.stringify(step)}`);
}
return `
(async () => {
const targetCount = ${targetCount};
const maxRounds = ${maxRounds};
const budgetMs = ${budgetMs};
const configuredStep = ${step};
const webHost = ${JSON.stringify(webHost)};
const noteUrlInfo = ${noteUrlInfo.toString()};
const mergeHarvestedRow = ${mergeHarvestedRow.toString()};
const stripXhsAuthorDateSuffix = ${stripXhsAuthorDateSuffix.toString()};
const extractSearchRows = ${extractSearchRows.toString()};
const usableRowCount = ${usableRowCount.toString()};
const shouldStopScrolling = ${shouldStopScrolling.toString()};
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));View on GitHub (pinned to 49907e53dc)
Solutions
- Pass a finite positive number of milliseconds, e.g. { budgetMs: 30_000 }.
- Convert duration strings to ms before passing (30s -> 30000).
- Omit options.budgetMs to use the 30s default.
- Sanitize with Number() and Number.isFinite before constructing options.
Example fix
// before
buildScrollHarvestJs(host, target, { budgetMs: config.timeoutSeconds });
// after
const budgetMs = Number(config.timeoutSeconds) * 1000;
if (!Number.isFinite(budgetMs) || budgetMs <= 0) throw new Error('bad budget');
buildScrollHarvestJs(host, target, { budgetMs }); Defensive patterns
Strategy: validation
Validate before calling
function assertBudgetMs(v) {
if (!Number.isFinite(v) || v <= 0) {
throw new TypeError(`budgetMs must be a positive finite number, got ${JSON.stringify(v)}`);
}
}
assertBudgetMs(options.budgetMs ?? 30_000); Type guard
const isValidBudgetMs = (v) => v === undefined || (Number.isFinite(v) && v > 0);
Prevention
- Always pass milliseconds, not seconds or duration strings.
- Convert strings like '30s' to numbers before passing.
- Check Number.isFinite — Infinity and NaN both fail validation.
- Default to 30_000 rather than hand-rolling small values like 0.
- Centralize duration parsing in one utility to avoid unit mistakes.
When it happens
Trigger: Passing options { budgetMs: 0 }, a negative duration, NaN/Infinity, or a non-number (e.g. '30000' string) to buildScrollHarvestJs.
Common situations: Parsing a duration string like '30s' and passing the raw string; config value 0 intended as 'no budget'; multiplying undefined by 1000 yielding NaN; passing seconds (30) while assuming the API converts units — use milliseconds.
Related errors
- targetCount must be a positive integer, got ${JSON.stringify
- maxScrolls must be a positive integer, got ${JSON.stringify(
- maxRounds must be a positive integer, got ${JSON.stringify(m
- step must be a non-negative number, got ${JSON.stringify(ste
- Omni Reference accepts exactly one local image
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/38510734111050d7.
Report an issue: GitHub.