JuliusBrussee/caveman · error
filter monitor.verdict must be pass, fail, or error
Error message
filter monitor.verdict must be pass, fail, or error
What it means
A `monitor` filter present in trace_search must carry `verdict` as one of the exact strings "pass", "fail", or "error". Any other string, a non-string, or a missing verdict throws this error listing the allowed values.
Solutions
- Set monitor.verdict to exactly one of "pass", "fail", or "error" (lowercase).
- Normalize/toLowerCase and map synonyms (success->pass, failure->fail) before the call.
- Omit the monitor filter if you don't need verdict filtering rather than sending a partial monitor object.
- Match the enum against the tool schema at build time to catch drift.
Example fix
// before
{ "filter": { "monitor": { "id": "m_1", "verdict": "Passed" } } }
// after
{ "filter": { "monitor": { "id": "m_1", "verdict": "pass" } } } Defensive patterns
Strategy: validation
Validate before calling
const VERDICTS = ["pass", "fail", "error"];
if (filter.monitor && !VERDICTS.includes(filter.monitor.verdict))
throw new Error(`monitor.verdict must be one of ${VERDICTS.join(", ")}`); Type guard
function isMonitorVerdict(v) {
return v === "pass" || v === "fail" || v === "error";
} Try / catch
try {
await traceSearch(args);
} catch (e) {
if (e.message.includes("monitor.verdict must be pass, fail, or error")) {
args.filter.monitor.verdict = String(args.filter.monitor.verdict).toLowerCase();
return traceSearch(args);
}
throw e;
} Prevention
- Use a const enum/union type for verdict values in client code.
- Normalize casing and map synonyms before sending.
- Copy enum values from the tool schema, not from UI labels.
When it happens
Trigger: Calling trace_search with {"filter":{"monitor":{"id":"m_1","verdict":"passed"}}} (wrong spelling), {"verdict":null}, {"verdict":"PASS"} (case-sensitive), or omitting verdict entirely while supplying id.
Common situations: Case sensitivity mistakes ("Pass"); using synonyms like "success"/"failed"; older payloads using different verdict vocabularies; UI sending a localized label instead of the enum value.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- filter monitor has unknown key(s)
- filter monitor.id is required
- filter status_class values must be 2xx, 4xx, or 5xx
- must be one of
- assembly slot has unknown stability
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/9dc9d92d3cf7e227.
Report an issue: GitHub.
Appendix: source
Thrown at packages/cli/src/agent-mcp.ts:495
}
for (const key of ["min_cost_usd", "max_cost_usd", "min_total_tokens", "max_total_tokens", "min_latency_ms", "max_latency_ms"]) {
const value = filters[key];
if (value !== undefined && (typeof value !== "number" || !Number.isFinite(value))) {
throw new Error(`filter ${key} must be a finite number`);
}
}
for (const key of ["has_error", "compressed"]) {
const value = filters[key];
if (value !== undefined && typeof value !== "boolean") throw new Error(`filter ${key} must be a boolean`);
}
const monitor = filters.monitor;
if (monitor !== undefined) {
if (!monitor || typeof monitor !== "object" || Array.isArray(monitor)) throw new Error("filter monitor must be an object");
const monitorUnknown = Object.keys(monitor).filter((key) => key !== "id" && key !== "verdict");
if (monitorUnknown.length > 0) throw new Error(`filter monitor has unknown key(s): ${monitorUnknown.sort().join(", ")}`);
if (typeof monitor.id !== "string" || monitor.id.trim() === "") throw new Error("filter monitor.id is required");
if (typeof monitor.verdict !== "string" || !["pass", "fail", "error"].includes(monitor.verdict)) {
throw new Error("filter monitor.verdict must be pass, fail, or error");
}
}
}
function optionalEnum(args: JSONObject, key: string, values: string[]): void {
const value = args[key];
if (value !== undefined && (typeof value !== "string" || !values.includes(value))) {
throw new Error(`${key} must be one of ${values.join(", ")}`);
}
}
function validateTraceSearch(args: JSONObject): void {
validateTraceFilters(args);
for (const key of ["from", "to"]) {
const value = args[key];
if (value !== undefined && typeof value !== "string") throw new Error(`${key} must be a string`);
}
optionalEnum(args, "date_field", ["occurred", "updated"]);View on GitHub (pinned to 3ee70a1026)