{"record":{"id":"0fc0057ea7a1fe4a","repo":"jackwener/OpenCLI","slug":"name-must-be-max","errorCode":null,"errorMessage":"${name} must be <= ${max}","messagePattern":"(.+?) must be <= (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/pinterest/utils.js","lineNumber":33,"sourceCode":"\n/** Unwrap the { session, data } envelope some browser-bridge versions add. */\nexport function unwrapEvaluateResult(payload) {\n  const isEnvelope = payload\n    && typeof payload === 'object'\n    && !Array.isArray(payload)\n    && 'session' in payload\n    && 'data' in payload;\n  return isEnvelope ? payload.data : payload;\n}\n\n/** Validate a positive-integer limit (throws instead of silently clamping). */\nexport function requireLimit(value, { fallback, max, name = 'limit' }) {\n  const parsed = Number(value ?? fallback);\n  if (!Number.isInteger(parsed) || parsed <= 0) {\n    throw new ArgumentError(`${name} must be a positive integer`, `e.g. --${name} 10`);\n  }\n  if (max && parsed > max) {\n    throw new ArgumentError(`${name} must be <= ${max}`, `Lower --${name} to ${max} or below`);\n  }\n  return parsed;\n}\n\n/**\n * Fold a slug for comparison. Pinterest keeps non-ASCII characters in slugs (e.g.\n * `naive-café-中文`) and stores them NFC, but a pasted or keyboard-composed accent can arrive as\n * NFD, which compares unequal byte-wise.\n */\nexport function normalizeForMatch(value) {\n  return String(value ?? '').normalize('NFC').trim().toLowerCase().replace(/\\s+/g, ' ');\n}\n\n/**\n * Pinterest path prefixes that are site routes, not usernames. Without this a pin URL parses as\n * the board `pin/<id>` and fails with a confusing \"could not resolve board\".\n */\nconst RESERVED_PATH_ROOTS = new Set(['pin', 'search', 'ideas', 'today', 'settings', '_saved', 'news_hub', 'business']);","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/pinterest/utils.js#L15-L51","documentation":"requireLimit also enforces an optional maximum. When a max option is provided and the parsed limit exceeds it, this ArgumentError is thrown telling the caller to lower the value. It exists to keep requests within API page-size limits instead of letting oversized requests fail downstream.","triggerScenarios":"Calling requireLimit(value, { max: 100 }) with value = 500, or CLI input like --limit 1000 against a helper configured with a smaller max.","commonSituations":"Users guessing at a 'fetch everything' page size; copy-pasted limits from another API's docs; a config raised after the library tightened its max; confusion between item count and page count.","solutions":["Lower the limit to at most the stated max, e.g. use 100 when max is 100","Paginate: call repeatedly with limit <= max until results are exhausted","Check the max configured at the call site (grep for requireLimit(...) options)","If the max is legitimately too small for your use, use the paginating helper instead of raising max"],"exampleFix":"// before\nconst limit = requireLimit(input, { max: 100 }); // input = 500\n// after\nconst limit = Math.min(Number(input) || 25, 100);\nconst clamped = requireLimit(limit, { max: 100 });","handlingStrategy":"validation","validationCode":"const MAX = 100;\nconst n = Number(input);\nif (Number.isInteger(n) && n > MAX) {\n  console.warn(`limit ${n} exceeds max ${MAX}, clamping`);\n  input = MAX;\n}","typeGuard":"const withinMax = (v, max) => Number.isSafeInteger(v) && v > 0 && v <= max;","tryCatchPattern":"try {\n  limit = requireLimit(input, { max: 100 });\n} catch (err) {\n  if (err instanceof ArgumentError && /must be <=/.test(err.message)) {\n    limit = 100; // clamp to max\n  } else throw err;\n}","preventionTips":["Clamp user input with Math.min(input, max) before calling","Paginate instead of requesting oversized pages","Document the max next to your CLI flag definition","Check the library's documented page-size cap when upgrading versions"],"tags":["validation","argument-error","limit-exceeded","pagination"],"backgroundTag":"limit-exceeds-maximum","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}