jackwener/OpenCLI · error · ArgumentError

--offset must be a multiple of 10 for DuckDuckGo HTML pagina

Error message

--offset must be a multiple of 10 for DuckDuckGo HTML pagination

What it means

The DuckDuckGo HTML search command validates its --offset argument and requires it to align with DuckDuckGo's HTML result pages, which contain 10 results per page. An offset not divisible by 10 cannot map to a page, so an ArgumentError is thrown before any request is made.

Source

Thrown at clis/duckduckgo/search.js:93

  access: 'read',
  description: 'Search DuckDuckGo',
  domain: 'html.duckduckgo.com',
  strategy: Strategy.PUBLIC,
  browser: true,
  args: [
    { name: 'keyword', positional: true, required: true, help: 'Search query' },
    { name: 'limit', type: 'int', default: 10, help: 'Number of results per page (1-10). For multi-page, use --offset' },
    { name: 'offset', type: 'int', default: 0, help: 'Result offset for pagination (0, 10, 20...). Uses XHR POST internally' },
    { name: 'region', help: 'Region code (e.g. jp-jp, us-en, cn-zh). Default: all regions' },
    { name: 'time', help: 'Time range: d (day), w (week), m (month), y (year)' },
  ],
  columns: ['rank', 'title', 'url', 'snippet', 'displayUrl', 'icon', 'resultType'],
  func: async (page, kwargs) => {
    const limit = requireBoundedInteger(kwargs.limit, 10, 1, 10, '--limit');
    const keyword = requireSearchQuery(kwargs.keyword);
    const offset = requireNonNegativeInteger(kwargs.offset, 0, '--offset');
    if (offset % 10 !== 0) {
      throw new ArgumentError('--offset must be a multiple of 10 for DuckDuckGo HTML pagination');
    }
    if (kwargs.time && !/^(d|w|m|y)$/.test(String(kwargs.time))) {
      throw new ArgumentError('--time must be one of d, w, m, or y');
    }
    let url = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(keyword)}`;
    if (kwargs.region) url += `&kl=${encodeURIComponent(String(kwargs.region))}`;
    if (kwargs.time) url += `&df=${encodeURIComponent(String(kwargs.time))}`;
    await runBrowserStep('duckduckgo search navigation', () => page.goto(url));
    try {
      await page.wait({ selector: '.result', timeout: 8 });
    } catch {
      await page.wait(3).catch(function() {});
    }
    var raw;
    if (offset === 0) {
      raw = await runBrowserStep('duckduckgo search extraction', () => page.evaluate(buildExtractorJs(limit)));
    } else {
      raw = await runBrowserStep('duckduckgo search pagination extraction', () => page.evaluate(buildPaginateJs(limit, keyword, offset, kwargs.region)));

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Round the offset down to the nearest multiple of 10 (e.g. Math.floor(offset / 10) * 10)
  2. Use offsets 0, 10, 20, ... for successive pages
  3. Increase --limit (max 10) rather than fine-grained offsets to reach more results
  4. Catch ArgumentError and show the constraint to the CLI user

Example fix

// before
await ddgSearch({ keyword: 'cats', offset: 13 });
// after
const offset = Math.floor(rawOffset / 10) * 10;
await ddgSearch({ keyword: 'cats', offset });
Defensive patterns

Strategy: validation

Validate before calling

const n = Number(offset);
if (!Number.isInteger(n) || n < 0 || n % 10 !== 0) {
  throw new Error('--offset must be a non-negative multiple of 10');
}

Type guard

function isValidOffset(v) {
  return Number.isInteger(v) && v >= 0 && v % 10 === 0;
}

Prevention

When it happens

Trigger: Calling the duckduckgo search command with --offset set to a value like 5, 13, or 25 instead of 0, 10, 20...

Common situations: Implementing custom pagination loops that increment offset by page-size values other than 10; reusing offsets taken from another search API; hand-typing an offset to skip a few results.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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