{"record":{"id":"ceb3435b785c4362","repo":"jackwener/OpenCLI","slug":"offset-must-be-a-multiple-of-10-for-duckduckgo-h","errorCode":null,"errorMessage":"--offset must be a multiple of 10 for DuckDuckGo HTML pagination","messagePattern":"--offset must be a multiple of 10 for DuckDuckGo HTML pagination","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/duckduckgo/search.js","lineNumber":93,"sourceCode":"  access: 'read',\n  description: 'Search DuckDuckGo',\n  domain: 'html.duckduckgo.com',\n  strategy: Strategy.PUBLIC,\n  browser: true,\n  args: [\n    { name: 'keyword', positional: true, required: true, help: 'Search query' },\n    { name: 'limit', type: 'int', default: 10, help: 'Number of results per page (1-10). For multi-page, use --offset' },\n    { name: 'offset', type: 'int', default: 0, help: 'Result offset for pagination (0, 10, 20...). Uses XHR POST internally' },\n    { name: 'region', help: 'Region code (e.g. jp-jp, us-en, cn-zh). Default: all regions' },\n    { name: 'time', help: 'Time range: d (day), w (week), m (month), y (year)' },\n  ],\n  columns: ['rank', 'title', 'url', 'snippet', 'displayUrl', 'icon', 'resultType'],\n  func: async (page, kwargs) => {\n    const limit = requireBoundedInteger(kwargs.limit, 10, 1, 10, '--limit');\n    const keyword = requireSearchQuery(kwargs.keyword);\n    const offset = requireNonNegativeInteger(kwargs.offset, 0, '--offset');\n    if (offset % 10 !== 0) {\n      throw new ArgumentError('--offset must be a multiple of 10 for DuckDuckGo HTML pagination');\n    }\n    if (kwargs.time && !/^(d|w|m|y)$/.test(String(kwargs.time))) {\n      throw new ArgumentError('--time must be one of d, w, m, or y');\n    }\n    let url = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(keyword)}`;\n    if (kwargs.region) url += `&kl=${encodeURIComponent(String(kwargs.region))}`;\n    if (kwargs.time) url += `&df=${encodeURIComponent(String(kwargs.time))}`;\n    await runBrowserStep('duckduckgo search navigation', () => page.goto(url));\n    try {\n      await page.wait({ selector: '.result', timeout: 8 });\n    } catch {\n      await page.wait(3).catch(function() {});\n    }\n    var raw;\n    if (offset === 0) {\n      raw = await runBrowserStep('duckduckgo search extraction', () => page.evaluate(buildExtractorJs(limit)));\n    } else {\n      raw = await runBrowserStep('duckduckgo search pagination extraction', () => page.evaluate(buildPaginateJs(limit, keyword, offset, kwargs.region)));","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/duckduckgo/search.js#L75-L111","documentation":"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.","triggerScenarios":"Calling the duckduckgo search command with --offset set to a value like 5, 13, or 25 instead of 0, 10, 20...","commonSituations":"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.","solutions":["Round the offset down to the nearest multiple of 10 (e.g. Math.floor(offset / 10) * 10)","Use offsets 0, 10, 20, ... for successive pages","Increase --limit (max 10) rather than fine-grained offsets to reach more results","Catch ArgumentError and show the constraint to the CLI user"],"exampleFix":"// before\nawait ddgSearch({ keyword: 'cats', offset: 13 });\n// after\nconst offset = Math.floor(rawOffset / 10) * 10;\nawait ddgSearch({ keyword: 'cats', offset });","handlingStrategy":"validation","validationCode":"const n = Number(offset);\nif (!Number.isInteger(n) || n < 0 || n % 10 !== 0) {\n  throw new Error('--offset must be a non-negative multiple of 10');\n}","typeGuard":"function isValidOffset(v) {\n  return Number.isInteger(v) && v >= 0 && v % 10 === 0;\n}","tryCatchPattern":null,"preventionTips":["Increment page offsets by 10 in pagination loops","Convert other APIs' page numbers: offset = (page - 1) * 10","Validate user-supplied offsets at the CLI boundary"],"tags":["argument-validation","pagination","cli"],"backgroundTag":"invalid-argument-value","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}