{"record":{"id":"9705716c1025b87d","repo":"JuliusBrussee/caveman","slug":"key-must-be-one-of-values-join","errorCode":null,"errorMessage":"${key} must be one of ${values.join(\", \")}","messagePattern":"(.+?) must be one of (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/cli/src/agent-mcp.ts","lineNumber":503,"sourceCode":"    const value = filters[key];\n    if (value !== undefined && typeof value !== \"boolean\") throw new Error(`filter ${key} must be a boolean`);\n  }\n  const monitor = filters.monitor;\n  if (monitor !== undefined) {\n    if (!monitor || typeof monitor !== \"object\" || Array.isArray(monitor)) throw new Error(\"filter monitor must be an object\");\n    const monitorUnknown = Object.keys(monitor).filter((key) => key !== \"id\" && key !== \"verdict\");\n    if (monitorUnknown.length > 0) throw new Error(`filter monitor has unknown key(s): ${monitorUnknown.sort().join(\", \")}`);\n    if (typeof monitor.id !== \"string\" || monitor.id.trim() === \"\") throw new Error(\"filter monitor.id is required\");\n    if (typeof monitor.verdict !== \"string\" || ![\"pass\", \"fail\", \"error\"].includes(monitor.verdict)) {\n      throw new Error(\"filter monitor.verdict must be pass, fail, or error\");\n    }\n  }\n}\n\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\");","sourceCodeStart":485,"sourceCodeEnd":521,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/cli/src/agent-mcp.ts#L485-L521","documentation":"optionalEnum() validates optional enumerated arguments on caveman_trace_search: date_field must be \"occurred\" or \"updated\", group_by must be \"session\", \"workflow\", \"model\", or \"member\" (and within sort, by must be timestamp/total_cost_usd/latency_ms/total_tokens and dir must be asc/desc). Any non-member string (or non-string value) throws with the key and the accepted list in the message.","triggerScenarios":"date_field: \"created\"; group_by: \"trace\" or \"agent\"; sort.dir: \"ascending\"; a number or null where the enum is expected.","commonSituations":"Guessing plausible values not in the schema; version skew where an older CLI lacks a newer enum member; models free-typing the enum.","solutions":["Read the accepted values straight from the error message and use one verbatim.","Omit the argument when unsure — every optionalEnum argument is optional.","Upgrade the caveman CLI if you expected a value (e.g. a new group_by member) that this version rejects."],"exampleFix":"// before\n{ date_field: \"created\", group_by: \"trace\" }\n\n// after\n{ date_field: \"occurred\", group_by: \"session\" }","handlingStrategy":"validation","validationCode":"function checkEnum(value: unknown, key: string, allowed: string[]): void {\n  if (value !== undefined && (typeof value !== \"string\" || !allowed.includes(value))) {\n    throw new Error(`${key} must be one of ${allowed.join(\", \")}`);\n  }\n}\ncheckEnum(args.date_field, \"date_field\", [\"occurred\", \"updated\"]);\ncheckEnum(args.group_by, \"group_by\", [\"session\", \"workflow\", \"model\", \"member\"]);","typeGuard":"function isEnum<T extends string>(v: unknown, allowed: readonly T[]): v is T {\n  return typeof v === \"string\" && (allowed as readonly string[]).includes(v);\n}","tryCatchPattern":null,"preventionTips":["Copy allowed values from the tool schema, not from memory.","Treat every enum arg as optional; omit rather than guess."],"tags":["mcp","validation","enum","traces"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}