{"record":{"id":"bdf54cde2a1893d5","repo":"jackwener/OpenCLI","slug":"crates-label-must-be-maxvalue","errorCode":null,"errorMessage":"crates ${label} must be <= ${maxValue}","messagePattern":"crates (.+?) must be <= (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/crates/utils.js","lineNumber":35,"sourceCode":"    const s = String(value ?? '').trim();\n    if (!s) throw new ArgumentError('crates crate name is required (e.g. \"serde\", \"tokio\")');\n    if (!CRATE_NAME.test(s)) {\n        throw new ArgumentError(\n            `crates crate name \"${value}\" is not a valid crates.io name`,\n            'Names start with an ASCII letter, then 0-63 chars of letters / digits / \"_-\".',\n        );\n    }\n    return s;\n}\n\nexport function requireBoundedInt(value, defaultValue, maxValue, label = 'limit') {\n    const raw = value ?? defaultValue;\n    const n = typeof raw === 'number' ? raw : Number(raw);\n    if (!Number.isInteger(n) || n <= 0) {\n        throw new ArgumentError(`crates ${label} must be a positive integer`);\n    }\n    if (n > maxValue) {\n        throw new ArgumentError(`crates ${label} must be <= ${maxValue}`);\n    }\n    return n;\n}\n\nexport async function cratesFetch(url, label) {\n    let resp;\n    try {\n        // crates.io requires a descriptive User-Agent per https://crates.io/data-access\n        resp = await fetch(url, { headers: { 'user-agent': UA, accept: 'application/json' } });\n    }\n    catch (err) {\n        throw new CommandExecutionError(\n            `${label} request failed: ${err?.message ?? err}`,\n            'Check that crates.io is reachable from this network.',\n        );\n    }\n    if (resp.status === 404) {\n        throw new EmptyResultError(label, `crates.io returned 404 for ${url}.`);","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/crates/utils.js#L17-L53","documentation":"requireBoundedInt enforces an upper bound on integer arguments (label defaults to 'limit'); values above maxValue throw this ArgumentError (e.g. 'crates limit must be <= 100'). This keeps requests within what the crates.io API (per_page) and the adapter are willing to serve.","triggerScenarios":"Calling `crates search` with --limit greater than 100 (the maxValue used by search), or any other adapter call whose label-specific max is exceeded, e.g. --limit 500.","commonSituations":"Trying to fetch 'everything' with a huge limit, porting a limit from another API with a different cap, or computing a limit dynamically (e.g. total results count) and passing it straight through.","solutions":["Cap the value at the documented maximum (100 for search) before calling.","Use Math.min(limit, 100) when deriving the limit programmatically.","Paginate with repeated calls if you need more than the maximum results.","Catch ArgumentError and re-prompt with the valid range."],"exampleFix":"// before\nawait cli.crates.search({ query: 'serde', limit: 1000 });\n// after\nawait cli.crates.search({ query: 'serde', limit: Math.min(userLimit, 100) });","handlingStrategy":"validation","validationCode":"const MAX_SEARCH_LIMIT = 100;\nfunction clampLimit(raw) {\n  const n = Number(raw);\n  if (!Number.isInteger(n) || n <= 0) throw new Error('limit must be a positive integer');\n  if (n > MAX_SEARCH_LIMIT) throw new Error(`limit must be <= ${MAX_SEARCH_LIMIT}`);\n  return n;\n}","typeGuard":"function isWithinLimit(v, max) {\n  return typeof v === 'number' && Number.isInteger(v) && v > 0 && v <= max;\n}","tryCatchPattern":"try {\n  await cli.crates.search({ query, limit });\n} catch (e) {\n  if (e instanceof ArgumentError && /must be <= \\d+/.test(e.message)) {\n    return cli.crates.search({ query, limit: 100 });\n  }\n  throw e;\n}","preventionTips":["Clamp dynamic limits with Math.min(n, maxValue) before calling.","Remember search caps at 100 results per request; paginate for more.","Document the max in your wrapper's help text.","Never pass a total-count as a per-request limit."],"tags":["argument-validation","bounds-check","crates-io"],"backgroundTag":"argument-out-of-range","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}