JuliusBrussee/caveman · error · Error
filter monitor.id is required
Error message
filter monitor.id is required
What it means
Thrown by the caveman agent MCP server (agent-mcp.ts) while validating a caveman_trace_search tool call. When the optional filters.monitor object is present, BOTH of its keys are mandatory: monitor.id must be a non-blank string and monitor.verdict must be pass|fail|error. This error fires when monitor.id is missing, not a string, or whitespace-only, aborting the call before any /api/v1/traces/search request is issued.
Source
Thrown at packages/cli/src/agent-mcp.ts:493
throw new Error("filter status_class values must be 2xx, 4xx, or 5xx");
}
}
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`);View on GitHub (pinned to 766dce6b13)
Solutions
- Set filters.monitor.id to a non-empty string, e.g. filters: { monitor: { id: "mon-42", verdict: "fail" } }
- Include monitor.verdict too — id alone will throw the sibling 'verdict' error next
- Omit filters.monitor entirely when monitor-scoped results are not needed
Example fix
// before
const args = { filters: { monitor: { verdict: "fail" } } };
await callTool("caveman_trace_search", args);
// after
const args = { filters: { monitor: { id: "mon-42", verdict: "fail" } } };
await callTool("caveman_trace_search", args); Defensive patterns
Strategy: validation
Validate before calling
const okMonitorId = (f = {}) =>
f.monitor === undefined ||
(typeof f.monitor?.id === "string" && f.monitor.id.trim() !== "");
if (!okMonitorId(args.filters)) throw new Error("monitor.id required before calling caveman_trace_search"); Type guard
const isNonEmptyString = (v: unknown): v is string => typeof v === "string" && v.trim() !== "";
Try / catch
const res = await client.callTool({ name: "caveman_trace_search", arguments });
if (res.isError) {
const text = res.content?.[0]?.text ?? "";
if (text.includes("monitor.id is required")) {
// drop the incomplete monitor filter and retry once without it
delete arguments.filters?.monitor;
} else throw new Error(text);
} Prevention
- Treat filters.monitor as an all-or-nothing pair: always set both id and verdict together
- Fetch valid monitor ids from the traces/monitor API before filtering on them
- Validate args against the tool inputSchema before every callTool
When it happens
Trigger: Calling MCP tool caveman_trace_search with filters.monitor that omits id (e.g. { monitor: { verdict: "pass" } }), sets monitor.id to a number/null, or passes a blank string like " ". Unknown extra keys inside monitor throw a different error first, so reaching this line means only id/verdict keys are present and id failed its check.
Common situations: An agent assumes verdict alone selects monitor-scoped traces; a partial monitor filter is copied from an earlier trace response; a user trims a larger filter down and drops the id field; monitor id is generated as a number and passed unstringified.
Related errors
- filter monitor.verdict must be pass, fail, or error
- ${key} must be one of ${values.join(", ")}
- ${key} must be a string
- page_size must be an integer from 1 to 500
- sort must be an object
AI-assisted analysis of JuliusBrussee/caveman@766dce6b13 (2026-08-18).
Data as JSON: /api/errors/8f376c2db4fdfaab.
Report an issue: GitHub.