jackwener/OpenCLI · error · ArgumentError

targetCount must be a positive integer, got ${JSON.stringify

Error message

targetCount must be a positive integer, got ${JSON.stringify(targetCount)}

What it means

buildScrollUntilJs validates that targetCount is a safe integer >= 1 before generating its scroll-until-enough browser IIFE, throwing this ArgumentError immediately otherwise. The parameter sets how many visible note rows to scroll until, so an invalid value would produce broken injected JS. This is a synchronous, fail-fast argument validation error at JS build time, not a page/automation failure.

Source

Thrown at clis/xiaohongshu/search.js:541

/**
 * Build a "scroll until enough or plateaued" IIFE used in place of a fixed
 * `autoScroll({ times: N })`. Xiaohongshu's search results page lazy-loads
 * ~5-7 notes per scroll, so the previous `times: 2` capped extraction at
 * ~13 items regardless of `--limit` (see #1471). This helper drives scrolls
 * dynamically:
 *
 *   - count visible `section.note-item` rows (excluding related-search
 *     `.query-note-item` rows)
 *   - if count >= targetCount → break (got enough)
 *   - if two consecutive scrolls add no new rows → break (DOM plateaued,
 *     no more lazy-load available)
 *   - hard cap at `maxScrolls` iterations (default 15) to bound runtime
 *
 * Exported so the rednote adapter (same DOM shape) can reuse it.
 */
export function buildScrollUntilJs(targetCount, maxScrolls = 15) {
    if (!Number.isSafeInteger(targetCount) || targetCount < 1) {
        throw new ArgumentError(`targetCount must be a positive integer, got ${JSON.stringify(targetCount)}`);
    }
    if (!Number.isSafeInteger(maxScrolls) || maxScrolls < 1) {
        throw new ArgumentError(`maxScrolls must be a positive integer, got ${JSON.stringify(maxScrolls)}`);
    }
    return `
      (async () => {
        const isVisibleNote = (el) => {
          if (el.classList.contains('query-note-item')) return false;
          const rect = el.getBoundingClientRect();
          if (rect.width <= 0 || rect.height <= 0) return false;
          const style = getComputedStyle(el);
          return style.display !== 'none' && style.visibility !== 'hidden';
        };
        // Note containers: legacy \`section.note-item\` first, fallback to
        // any \`<section>\` that wraps a search-result/explore note link
        // (#1506 reports the class being dropped on some xhs renders).
        const collectNoteCards = () => {
          const classMatches = document.querySelectorAll('section.note-item');

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a positive safe integer, e.g. buildScrollUntilJs(50).
  2. If the value comes from user input, parse and validate it: Number.isSafeInteger(Number.parseInt(raw, 10)).
  3. Coerce with Math.max(1, Math.trunc(n)) after confirming the value is finite.
  4. Check upstream callers to find where undefined/null leaked into the argument.

Example fix

// before
const js = buildScrollUntilJs(process.env.LIMIT);
// after
const limit = Number.parseInt(process.env.LIMIT ?? '20', 10);
if (!Number.isSafeInteger(limit) || limit < 1) {
  throw new Error(`invalid LIMIT: ${process.env.LIMIT}`);
}
const js = buildScrollUntilJs(limit);
Defensive patterns

Strategy: validation

Validate before calling

function assertPositiveInt(v, name) {
  if (!Number.isSafeInteger(v) || v < 1) {
    throw new TypeError(`${name} must be a positive safe integer, got ${JSON.stringify(v)}`);
  }
}
assertPositiveInt(targetCount, 'targetCount');

Type guard

const isPositiveInt = (v) => Number.isSafeInteger(v) && v >= 1;

Prevention

When it happens

Trigger: Calling buildScrollUntilJs(targetCount) directly (or the rednote adapter reusing it) with 0, a negative number, a non-number (string, undefined, NaN, Infinity), or a float.

Common situations: Passing an unparsed CLI --limit string; forgetting a default so the argument is undefined; a config object returning null/NaN; computing the limit from a parse that failed silently.

Related errors


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