{"record":{"id":"919f2eadfbdd379f","repo":"jackwener/OpenCLI","slug":"label-must-be-maxvalue","errorCode":null,"errorMessage":"${label} must be <= ${maxValue}","messagePattern":"(.+?) must be <= (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/1point3acres/utils.js","lineNumber":22,"sourceCode":" * Site is a Discuz!X PHP BBS that serves GBK-encoded HTML.\n * - Thread listings:  /bbs/forum.php?mod=guide&view={hot|new|digest|newthread}\n * - Forum:            /bbs/forum-<fid>-<page>.html\n * - Thread detail:    /bbs/thread-<tid>-<page>-1.html\n * - User profile:     /bbs/space-uid-<uid>.html  or  /bbs/space-username-<name>.html\n * - Search:           /bbs/search.php?mod=forum  (COOKIE — guests get an alert page)\n */\nimport { AuthRequiredError, ArgumentError, CommandExecutionError } from '@jackwener/opencli/errors';\n\nexport const BASE = 'https://www.1point3acres.com/bbs';\n\n/**\n * Validate `limit` per typed-fail-fast convention (no silent clamp).\n * 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';","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/1point3acres/utils.js#L4-L40","documentation":"ArgumentError from normalizeLimit, the typed-fail-fast limit validator. After coercing to a positive integer via normalizePositiveInteger, it rejects values exceeding the caller-specified maxValue instead of silently clamping, per the library's no-silent-clamp convention.","triggerScenarios":"Calling a 1point3acres command (e.g. search) with limit above the command's max (e.g. limit: 100 when max is 50); misreading the default limit as a max; copying a limit from another command with a different ceiling.","commonSituations":"Pagination loops that compute limit dynamically and overshoot the max; users asking for 'all results' by passing a huge limit; config files shared between commands with different caps.","solutions":["Lower limit to the command's documented maximum","Read the error message: it states the exact max allowed (e.g. 'limit must be <= 50')","If you truly need more results, paginate by increasing `page`/offset semantics rather than raising limit","Clamp explicitly in your own code before calling if deliberate: limit = Math.min(limit, MAX)","Note: no silent clamping — you must fix the value yourself"],"exampleFix":"// before\nsearch({ query: 'h1b', limit: 500 })  // ArgumentError: limit must be <= 50\n// after\nconst MAX = 50;\nsearch({ query: 'h1b', limit: Math.min(500, MAX) })","handlingStrategy":"validation","validationCode":"const MAX_LIMIT = 50; // per command docs\nconst safeLimit = (v) => {\n  const n = Number(v);\n  if (!Number.isInteger(n) || n <= 0) throw new Error('limit must be a positive integer');\n  return Math.min(n, MAX_LIMIT); // explicit clamp, your choice not the library's\n};","typeGuard":"const isUsableLimit = (v, max) =>\n  Number.isInteger(v) && v > 0 && v <= max;","tryCatchPattern":"try {\n  await search({ query, limit });\n} catch (e) {\n  if (e instanceof ArgumentError && /must be <=/.test(e.message)) {\n    const max = Number(e.message.match(/<= (\\d+)/)?.[1]);\n    await search({ query, limit: max });\n  } else throw e;\n}","preventionTips":["Clamp limit explicitly in your own code before calling","Read each command's documented max — caps differ per command","Parse CLI flags with parseInt so limits arrive as integers","Remember the library never silently clamps — decide the clamp yourself"],"tags":["argument-validation","limit","fail-fast"],"backgroundTag":"invalid-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}