{"record":{"id":"ffd3ee5738821c2e","repo":"JuliusBrussee/caveman","slug":"page-size-must-be-an-integer-from-1-to-500","errorCode":null,"errorMessage":"page_size must be an integer from 1 to 500","messagePattern":"page_size must be an integer from 1 to 500","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cli/src/agent-mcp.ts","lineNumber":517,"sourceCode":"\nfunction optionalEnum(args: JSONObject, key: string, values: string[]): void {\n  const value = args[key];\n  if (value !== undefined && (typeof value !== \"string\" || !values.includes(value))) {\n    throw new Error(`${key} must be one of ${values.join(\", \")}`);\n  }\n}\n\nfunction validateTraceSearch(args: JSONObject): void {\n  validateTraceFilters(args);\n  for (const key of [\"from\", \"to\"]) {\n    const value = args[key];\n    if (value !== undefined && typeof value !== \"string\") throw new Error(`${key} must be a string`);\n  }\n  optionalEnum(args, \"date_field\", [\"occurred\", \"updated\"]);\n  optionalEnum(args, \"group_by\", [\"session\", \"workflow\", \"model\", \"member\"]);\n  const pageSize = args.page_size;\n  if (pageSize !== undefined && (!Number.isSafeInteger(pageSize) || (pageSize as number) < 1 || (pageSize as number) > 500)) {\n    throw new Error(\"page_size must be an integer from 1 to 500\");\n  }\n  const sort = args.sort;\n  if (sort !== undefined) {\n    if (!sort || typeof sort !== \"object\" || Array.isArray(sort)) throw new Error(\"sort must be an object\");\n    const unknown = Object.keys(sort).filter((key) => key !== \"by\" && key !== \"dir\");\n    if (unknown.length > 0) throw new Error(`sort has unknown key(s): ${unknown.sort().join(\", \")}`);\n    optionalEnum(sort, \"by\", [\"timestamp\", \"total_cost_usd\", \"latency_ms\", \"total_tokens\"]);\n    optionalEnum(sort, \"dir\", [\"asc\", \"desc\"]);\n  }\n  const cursor = args.cursor;\n  if (cursor !== undefined) {\n    if (!cursor || typeof cursor !== \"object\" || Array.isArray(cursor)) throw new Error(\"cursor must be an object\");\n    const unknown = Object.keys(cursor).filter((key) => key !== \"sort_value\" && key !== \"request_id\" && key !== \"group_key\");\n    if (unknown.length > 0) throw new Error(`cursor has unknown key(s): ${unknown.sort().join(\", \")}`);\n    if (typeof cursor.sort_value !== \"string\" || cursor.sort_value === \"\") throw new Error(\"cursor.sort_value is required\");\n    for (const key of [\"request_id\", \"group_key\"]) {\n      if (cursor[key] !== undefined && typeof cursor[key] !== \"string\") throw new Error(`cursor.${key} must be a string`);\n    }","sourceCodeStart":499,"sourceCodeEnd":535,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/cli/src/agent-mcp.ts#L499-L535","documentation":"Validation error from validateTraceSearch in the agent MCP server: page_size is outside the accepted range — it must be an integer between 1 and 500. Enforced so trace listing requests stay bounded for the API call behind the tool.","triggerScenarios":"trace_search with {\"page_size\":0}, {\"page_size\":501}, {\"page_size\":10.5}, {\"page_size\":\"25\"} (string), or page_size from a config parsed as a string.","commonSituations":"CLI flags passed as strings and not converted; frontend sliders allowing 0 or huge values; pagination copied from APIs with 1000-item limits; NaN/Infinity from bad arithmetic (fails Number.isSafeInteger).","solutions":["Clamp page_size into [1, 500]: Math.min(500, Math.max(1, n)).","Round to an integer (Math.floor/round) before sending.","Coerce string values with Number()/parseInt and validate isSafeInteger.","Omit page_size to use the server default."],"exampleFix":"// before\n{ \"page_size\": 1000 }\n// after\n{ \"page_size\": 500 }","handlingStrategy":"validation","validationCode":"if (args.page_size !== undefined) {\n  const n = Number(args.page_size);\n  if (!Number.isSafeInteger(n) || n < 1 || n > 500)\n    throw new Error(\"page_size must be an integer 1-500\");\n  args.page_size = n;\n}","typeGuard":"function isValidPageSize(v) {\n  return v === undefined || (Number.isSafeInteger(v) && v >= 1 && v <= 500);\n}","tryCatchPattern":"try {\n  await traceSearch(args);\n} catch (e) {\n  if (e.message.startsWith(\"page_size must be\")) {\n    args.page_size = Math.min(500, Math.max(1, Math.round(Number(args.page_size) || 1)));\n    return traceSearch(args);\n  }\n  throw e;\n}","preventionTips":["Clamp UI inputs and CLI flags to 1-500 before calling.","Coerce numeric CLI/env strings with Number() and validate.","Cap client-side page size constants at 500."],"tags":["validation","pagination","mcp","range"],"backgroundTag":"value-out-of-range","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}