{"record":{"id":"bb394dd012e4b4e1","repo":"jackwener/OpenCLI","slug":"limit-must-be-an-integer-between-hot-min-limit","errorCode":null,"errorMessage":"--limit must be an integer between ${HOT_MIN_LIMIT} and ${HOT_MAX_LIMIT}, got ${JSON.stringify(raw)}","messagePattern":"--limit must be an integer between (.+?) and (.+?), got (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"warning","filePath":"clis/toutiao/utils.js","lineNumber":50,"sourceCode":"        throw new ArgumentError(`--limit must be between ${RECOMMEND_MIN_LIMIT} and ${RECOMMEND_MAX_LIMIT}, got ${parsed}`);\n    }\n    return parsed;\n}\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 *","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/toutiao/utils.js#L32-L68","documentation":"parseHotLimit validates the `--limit` option of the toutiao hot command. This throw fires when the value is not a finite integer (e.g. 'abc', '3.5', '1e3', NaN). The library requires an integer count of hot items so it can page the upstream API deterministically.","triggerScenarios":"Calling toutiao hot with --limit set to a non-integer or non-numeric string: --limit abc, --limit 3.5, --limit 10x, --limit NaN, or a shell variable that expanded to garbage.","commonSituations":"Passing float averages from prior computations; unquoted/unset shell variables interpolating empty or text; parsing JSON where the field was a string like \"30\" with units ('30 items'); typos like '--limit 3o'.","solutions":["Pass a plain integer between 1 and 50, e.g. --limit 30.","Parse/sanitize first: Number.parseInt(String(raw), 10) and check Number.isInteger before invoking.","Omit --limit to use the default of 30.","Fix the calling script so the shell variable is quoted and guaranteed numeric."],"exampleFix":"// before\ntoutiao hot --limit \"$LIMIT_ITEMS\"   # LIMIT_ITEMS='30 items'\n// after\ntoutiao hot --limit 30","handlingStrategy":"validation","validationCode":"const n = Number.parseInt(String(raw), 10);\nif (!Number.isInteger(n) || String(n) !== String(raw).trim()) throw new TypeError(`--limit must be an integer, got ${JSON.stringify(raw)}`);","typeGuard":"const isIntString = (v) => /^-?\\d+$/.test(String(v).trim());","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":["Quote shell variables and guarantee they contain only digits before invoking.","Strip units/suffixes ('30 items' -> 30) before passing.","Omit --limit to use the default of 30."],"tags":["cli","argument-validation","type-error","toutiao"],"backgroundTag":"cli-argument-type-mismatch","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}