{"record":{"id":"ccb5f2a407ed8d61","repo":"jackwener/OpenCLI","slug":"limit-must-be-an-integer-between-1-and-max-sea","errorCode":null,"errorMessage":"--limit must be an integer between 1 and ${MAX_SEARCH_LIMIT}, got ${JSON.stringify(raw)}","messagePattern":"--limit must be an integer between 1 and (.+?), got (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/douyin/search.js","lineNumber":56,"sourceCode":" *\n * Prerequisite: the bound Chrome profile must be logged in to\n * https://www.douyin.com. The search results page renders an empty\n * skeleton for anonymous visitors, which we surface as AuthRequiredError.\n */\nimport { cli, Strategy } from '@jackwener/opencli/registry';\nimport { ArgumentError, AuthRequiredError, CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';\n\nexport const MAX_SEARCH_LIMIT = 30;\n// Time budget for the SPA's initial DOM commit. Empirically the\n// scroll-list `<li>` rows appear within 2-4s of navigation when logged\n// in; 15s covers slow networks without blocking on a permanently-empty\n// page (anonymous gate, network error).\nexport const RENDER_TIMEOUT_MS = 15000;\n\nexport function parseSearchLimit(raw) {\n    const parsed = Number(raw ?? 10);\n    if (!Number.isFinite(parsed) || !Number.isInteger(parsed)) {\n        throw new ArgumentError(`--limit must be an integer between 1 and ${MAX_SEARCH_LIMIT}, got ${JSON.stringify(raw)}`);\n    }\n    if (parsed < 1 || parsed > MAX_SEARCH_LIMIT) {\n        throw new ArgumentError(`--limit must be between 1 and ${MAX_SEARCH_LIMIT}, got ${parsed}`);\n    }\n    return parsed;\n}\n\n/**\n * Parse a Douyin display count like \"1.9万\", \"3.1万\", \"4702\", \"1.2亿\"\n * into a plain integer. Returns 0 for unparseable input rather than\n * throwing — the CLI promises numeric columns and missing data is\n * common enough on real result rows that a soft fallback is the right\n * choice.\n */\nexport function parseDouyinCount(text) {\n    if (typeof text !== 'string') return 0;\n    const m = text.replace(/\\s/g, '').match(/^(\\d+(?:\\.\\d+)?)([万亿])?$/);\n    if (!m) {","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/douyin/search.js#L38-L74","documentation":"parseSearchLimit converts the --limit option with Number(raw ?? 10) and requires a finite integer before range-checking. Non-numeric or non-integer inputs (e.g. 'abc', '2.5', '') throw this ArgumentError, echoing the original value via JSON.stringify. This is the type/coercion check; the 1..MAX range check is the separate follow-up error.","triggerScenarios":"Calling the douyin search command with --limit set to a non-integer string, a non-numeric value, NaN-producing input like 'ten' or '1,000', or an empty string.","commonSituations":"CLI flags passed as free text by scripts; locale-formatted numbers ('1.000'); users assuming a range like '10-50' is accepted; YAML/JSON configs supplying strings instead of numbers.","solutions":["Pass an integer value for --limit, e.g. --limit 20","Remove thousands separators, units, or ranges from the value","Coerce/validate in the calling script before invoking: Number.isInteger(Number(raw))"],"exampleFix":"// before\nawait douyin.search({ query: 'cats', limit: '1,000' });\n// after\nawait douyin.search({ query: 'cats', limit: 50 });","handlingStrategy":"validation","validationCode":"function parseLimit(raw) {\n  const n = Number(raw ?? 10);\n  if (!Number.isFinite(n) || !Number.isInteger(n)) throw new TypeError(`--limit must be an integer, got ${JSON.stringify(raw)}`);\n  return n;\n}","typeGuard":"function isValidLimit(v) {\n  const n = Number(v);\n  return Number.isFinite(n) && Number.isInteger(n);\n}","tryCatchPattern":"try {\n  await douyin.search({ query, limit: rawLimit });\n} catch (e) {\n  if (e instanceof ArgumentError && /must be an integer/.test(e.message)) {\n    await douyin.search({ query, limit: 10 }); // fall back to default\n  } else throw e;\n}","preventionTips":["Coerce CLI/config values through Number() and Number.isInteger before passing","Strip thousands separators and units from user-supplied numbers","Centralize option parsing so all commands validate the same way"],"tags":["validation","argument-error","cli"],"backgroundTag":"invalid-argument-type","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}