{"record":{"id":"5a85a7198b0d03ff","repo":"jackwener/OpenCLI","slug":"label-must-be-min","errorCode":null,"errorMessage":"${label} must be >= ${min}","messagePattern":"(.+?) must be >= (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/1point3acres/utils.js","lineNumber":35,"sourceCode":" * Throws ArgumentError on non-positive / non-integer / out-of-range input.\n */\nexport function normalizeLimit(value, defaultValue, maxValue, label = 'limit') {\n    const limit = normalizePositiveInteger(value, defaultValue, label);\n    if (limit > maxValue) {\n        throw new ArgumentError(`${label} must be <= ${maxValue}`);\n    }\n    return limit;\n}\n\n/** Validate a positive integer argument without silently flooring/clamping. */\nexport function normalizePositiveInteger(value, defaultValue, label = 'value', { min = 1 } = {}) {\n    const raw = value ?? defaultValue;\n    const limit = Number(raw);\n    if (!Number.isInteger(limit) || limit <= 0) {\n        throw new ArgumentError(`${label} must be a positive integer`);\n    }\n    if (limit < min) {\n        throw new ArgumentError(`${label} must be >= ${min}`);\n    }\n    return limit;\n}\n\nconst UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0 Safari/537.36';\n\n/** Fetch a GBK-encoded Discuz page and return decoded UTF-8 HTML. */\nexport async function fetchHtml(url, { headers = {}, cookie = '' } = {}) {\n    let res;\n    try {\n        res = await fetch(url, {\n            headers: {\n                'User-Agent': UA,\n                'Accept': 'text/html,application/xhtml+xml',\n                'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',\n                ...(cookie ? { Cookie: cookie } : {}),\n                ...headers,\n            },","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/1point3acres/utils.js#L17-L53","documentation":"ArgumentError from normalizePositiveInteger's `min` option, thrown when a value is a valid positive integer but below the caller's configured minimum. Used e.g. for contentLimit with min: 50 — values like 10 are rejected rather than silently raised, keeping validation explicit.","triggerScenarios":"Passing contentLimit below 50 (e.g. contentLimit: 20) to the thread command; any command whose validator sets { min } and receives an integer smaller than that floor.","commonSituations":"Wanting shorter excerpts and guessing a small number without checking the minimum; copying a limit from another tool with a smaller floor; config default tuned for a different command.","solutions":["Raise the value to at least the stated minimum (contentLimit >= 50)","Read the error message: it names the exact minimum (e.g. 'contentLimit must be >= 50')","If you need less content, post-truncate the returned strings yourself instead of passing sub-minimum values","Omit the option to use the command default (contentLimit: 400)"],"exampleFix":"// before\nthread({ tid: '123', contentLimit: 20 })  // ArgumentError: contentLimit must be >= 50\n// after\nthread({ tid: '123', contentLimit: 50 })\n// or post-truncate yourself:\nconst t = await thread({ tid: '123' });\nconst short = t.rows.map(r => ({ ...r, content: r.content.slice(0, 20) }));","handlingStrategy":"validation","validationCode":"const CONTENT_LIMIT_MIN = 50;\nconst safeContentLimit = (v) => {\n  const n = Number(v);\n  if (!Number.isInteger(n) || n < CONTENT_LIMIT_MIN) throw new Error(`contentLimit must be an integer >= ${CONTENT_LIMIT_MIN}`);\n  return n;\n};","typeGuard":"const meetsMin = (v, min) => Number.isInteger(v) && v >= min;","tryCatchPattern":"try {\n  await thread({ tid, contentLimit });\n} catch (e) {\n  if (e instanceof ArgumentError && /must be >=/.test(e.message)) {\n    const min = Number(e.message.match(/>= (\\d+)/)?.[1]);\n    await thread({ tid, contentLimit: Math.max(contentLimit, min) });\n  } else throw e;\n}","preventionTips":["Check the min documented for each option (contentLimit min is 50)","For shorter excerpts, post-truncate results yourself instead of passing sub-minimum values","Omit the option to use the sensible default (400)","Centralize option validation so mins are enforced once"],"tags":["argument-validation","minimum-value","fail-fast"],"backgroundTag":"invalid-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}