{"record":{"id":"4498c2c146a5a589","repo":"JuliusBrussee/caveman","slug":"filter-monitor-must-be-an-object","errorCode":null,"errorMessage":"filter monitor must be an object","messagePattern":"filter monitor must be an object","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/cli/src/agent-mcp.ts","lineNumber":490,"sourceCode":"      throw new Error(`filter ${key} must be a non-empty array of non-empty strings`);\n    }\n    if (key === \"status_class\" && value.some((entry) => ![\"2xx\", \"4xx\", \"5xx\"].includes(entry as string))) {\n      throw new Error(\"filter status_class values must be 2xx, 4xx, or 5xx\");\n    }\n  }\n  for (const key of [\"min_cost_usd\", \"max_cost_usd\", \"min_total_tokens\", \"max_total_tokens\", \"min_latency_ms\", \"max_latency_ms\"]) {\n    const value = filters[key];\n    if (value !== undefined && (typeof value !== \"number\" || !Number.isFinite(value))) {\n      throw new Error(`filter ${key} must be a finite number`);\n    }\n  }\n  for (const key of [\"has_error\", \"compressed\"]) {\n    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);","sourceCodeStart":472,"sourceCodeEnd":508,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/cli/src/agent-mcp.ts#L472-L508","documentation":"The nested `monitor` filter must be a plain JSON object (with only id and verdict keys) when present. Passing null, an array, a string, or a number throws this error before the key-level monitor checks run.","triggerScenarios":"filters.monitor = \"mon_123\"; filters.monitor = [\"mon_123\"]; filters.monitor = null sent instead of omitting the key.","commonSituations":"Shorthand single-id forms; clients defaulting optional objects to null; double-encoded JSON strings.","solutions":["Pass monitor as an object: {\"monitor\": {\"id\": \"mon_123\", \"verdict\": \"pass\"}}.","Omit the monitor key entirely when not filtering by monitor.","Omit verdict if you only need id — only id is required inside monitor."],"exampleFix":"// before\n{ filters: { monitor: \"mon_123\" } }\n\n// after\n{ filters: { monitor: { id: \"mon_123\" } } }","handlingStrategy":"type-guard","validationCode":"if (filters.monitor !== undefined && (typeof filters.monitor !== \"object\" || filters.monitor === null || Array.isArray(filters.monitor))) {\n  throw new Error(\"monitor must be an object\");\n}","typeGuard":"function isMonitorFilter(v: unknown): v is { id?: string; verdict?: string } {\n  return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}","tryCatchPattern":null,"preventionTips":["Wrap monitor ids in { id: ... } objects.","Omit the monitor key when not filtering by monitor."],"tags":["mcp","validation","filters","monitor"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}