{"record":{"id":"35a7bdc5fb6c7f9d","repo":"jackwener/OpenCLI","slug":"limit-must-be-between-hot-min-limit-and-hot","errorCode":null,"errorMessage":"--limit must be between ${HOT_MIN_LIMIT} and ${HOT_MAX_LIMIT}, got ${parsed}","messagePattern":"--limit must be between (.+?) and (.+?), got (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"warning","filePath":"clis/toutiao/utils.js","lineNumber":53,"sourceCode":"}\n\nexport function parseRecommendCategory(raw, fallback = '__all__') {\n    if (raw === undefined || raw === null || raw === '') return fallback;\n    const value = String(raw).trim();\n    if (!RECOMMEND_CATEGORIES.includes(value)) {\n        throw new ArgumentError(`--category must be one of ${RECOMMEND_CATEGORIES.join(', ')}, got ${JSON.stringify(raw)}`);\n    }\n    return value;\n}\n\nexport function parseHotLimit(raw, fallback = 30) {\n    if (raw === undefined || raw === null || raw === '') return fallback;\n    const parsed = Number(raw);\n    if (!Number.isFinite(parsed) || !Number.isInteger(parsed)) {\n        throw new ArgumentError(`--limit must be an integer between ${HOT_MIN_LIMIT} and ${HOT_MAX_LIMIT}, got ${JSON.stringify(raw)}`);\n    }\n    if (parsed < HOT_MIN_LIMIT || parsed > HOT_MAX_LIMIT) {\n        throw new ArgumentError(`--limit must be between ${HOT_MIN_LIMIT} and ${HOT_MAX_LIMIT}, got ${parsed}`);\n    }\n    return parsed;\n}\n\nconst NON_TITLE_LINES = new Set([\n    '展现', '阅读', '点赞', '评论',\n    '查看数据', '查看评论', '修改', '更多', '首发',\n    '已发布', '定时发布', '定时发布中', '由文章生成', '审核中',\n]);\n\nconst STATS_RE = /展现\\s*([\\d,]+)\\s*阅读\\s*([\\d,]+)\\s*点赞\\s*([\\d,]+)\\s*评论\\s*([\\d,]*)/;\n\n/**\n * Extract creator-backend article rows from the rendered text dump.\n *\n * Surfaces every row anchored on a `MM-DD HH:MM` line; if the matching stats\n * line never came through (slow render / missing element), the row is still\n * emitted with `null` for stat columns rather than silently dropped.","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/toutiao/utils.js#L35-L71","documentation":"parseHotLimit validates the `--limit` option of the toutiao hot command. This specific throw fires when the value IS a valid integer but is outside the allowed range [HOT_MIN_LIMIT=1, HOT_MAX_LIMIT=50]. The bound keeps upstream requests valid and prevents over-fetching.","triggerScenarios":"Calling toutiao hot with an integer --limit < 1 (e.g. --limit 0) or > 50 (e.g. --limit 500). The Number()/isInteger() checks passed but the range comparison failed.","commonSituations":"Scripts scaling limit by a factor that lands above 50; loops computing limit from user data yielding 0; copying the limit convention from a different CLI whose max differs.","solutions":["Pass an integer between 1 and 50 for --limit (default is 30).","Clamp before invoking: Math.min(50, Math.max(1, n)).","Omit --limit to use the default of 30.","For more than 50 items, issue multiple calls or use a different endpoint that supports paging."],"exampleFix":"// before\ntoutiao hot --limit 0\n// after\ntoutiao hot --limit 1  # or omit for default 30","handlingStrategy":"validation","validationCode":"const n = Number(raw);\nif (!Number.isInteger(n) || n < 1 || n > 50) throw new RangeError(`--limit must be an integer between 1 and 50, got ${raw}`);","typeGuard":"const isValidHotLimit = (v) => Number.isInteger(v) && v >= 1 && v <= 50;","tryCatchPattern":"try {\n  parseHotLimit(raw);\n} catch (e) {\n  if (e instanceof ArgumentError) { console.error(e.message); process.exitCode = 2; }\n  else throw e;\n}","preventionTips":["Clamp computed limits: Math.min(50, Math.max(1, n)).","Guard loop-derived limits against 0/negative values.","Omit --limit to use the default of 30."],"tags":["cli","argument-validation","toutiao"],"backgroundTag":"cli-argument-out-of-range","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}