jackwener/OpenCLI · error · ArgumentError

maxScrolls must be an integer between 1 and 30, got ${JSON.s

Error message

maxScrolls must be an integer between 1 and 30, got ${JSON.stringify(maxScrolls)}

What it means

buildScrollUntilJs also validates its third parameter maxScrolls (default 8): it must be an integer between 1 and 30 inclusive. This caps how many scroll iterations the generated page script will perform, preventing unbounded scrolling. Non-integer or out-of-range values raise ArgumentError.

Source

Thrown at clis/ctrip/utils.js:466

      })()
    `;
}

/**
 * Build a scroll-until-enough IIFE for flights/hotels DOM-card pagination.
 *
 * Mirrors `clis/xiaohongshu/search.js#buildScrollUntilJs` (PR #1487) — counts a
 * caller-supplied row selector, scrolls until count >= target / DOM plateau /
 * maxScrolls. Returns final row count so the caller can decide whether to
 * surface an EmptyResultError. (xiaohongshu's helper hardcodes
 * `section.note-item`; this generic version takes a selector.)
 */
export function buildScrollUntilJs(rowSelector, targetCount, maxScrolls = 8) {
    if (!Number.isInteger(targetCount) || targetCount < 1 || targetCount > 100) {
        throw new ArgumentError(`targetCount must be an integer between 1 and 100, got ${JSON.stringify(targetCount)}`);
    }
    if (!Number.isInteger(maxScrolls) || maxScrolls < 1 || maxScrolls > 30) {
        throw new ArgumentError(`maxScrolls must be an integer between 1 and 30, got ${JSON.stringify(maxScrolls)}`);
    }
    return `
      (async () => {
        const sel = ${JSON.stringify(rowSelector)};
        const isVisible = (el) => {
          const style = window.getComputedStyle(el);
          if (style.display === 'none' || style.visibility === 'hidden' || Number(style.opacity) === 0) return false;
          const rect = el.getBoundingClientRect();
          return rect.width > 0 && rect.height > 0;
        };
        const countItems = () => Array.from(document.querySelectorAll(sel)).filter(isVisible).length;
        let lastCount = countItems();
        let plateauRounds = 0;
        for (let i = 0; i < ${maxScrolls}; i++) {
          if (countItems() >= ${targetCount}) break;
          const lastHeight = document.body.scrollHeight;
          window.scrollTo(0, lastHeight);
          await new Promise((resolve) => {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass an integer between 1 and 30 (or omit it to use the default 8).
  2. Clamp the value: Math.min(30, Math.max(1, Math.floor(Number(x)))).
  3. If the target count needs more scrolls, increase targetCount within limits or re-invoke the helper.

Example fix

// before
buildScrollUntilJs('.row', 20, 100)
// after
buildScrollUntilJs('.row', 20, 30)
Defensive patterns

Strategy: validation

Validate before calling

function clampMaxScrolls(v = 8) {
  const n = Number(v);
  if (!Number.isInteger(n) || n < 1 || n > 30) throw new Error('maxScrolls must be an integer 1-30');
  return n;
}

Type guard

const isValidMaxScrolls = (v) => Number.isInteger(v) && v >= 1 && v <= 30;

Try / catch

try {
  return buildScrollUntilJs(sel, count, maxScrolls);
} catch (e) {
  if (e instanceof ArgumentError && e.message.includes('maxScrolls')) {
    return buildScrollUntilJs(sel, count, 8); // library default
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling buildScrollUntilJs with maxScrolls = 0, negative, fractional (1.5), non-numeric types, or values over 30 such as 50 or 100.

Common situations: Consumers trying to 'scroll forever' by passing a huge maxScrolls, passing 0 expecting unlimited scrolls, or forwarding raw unparsed strings from CLI/config.

Understand the failure class

Background: "Unknown argument", "Invalid value", and "must be one of": invalid CLI argument errors explained — this error's family across 35 libraries.

Related errors


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