JuliusBrussee/caveman · error
filter monitor must be an object
Error message
filter monitor must be an object
What it means
The monitor filter, when present, must be a plain object (not null or an array). Subsequent checks require it to contain exactly the keys id and verdict — this specific error fires for the outer shape check before the id/verdict validation.
Solutions
- Pass monitor as an object: { id: '<monitor-id>', verdict: 'pass' | 'fail' | 'error' }
- Convert a bare id into { id, verdict } if you have the verdict
- Omit the monitor key when not filtering by monitor
Example fix
// before
searchTraces({ filters: { monitor: 'mon_123' } });
// after
searchTraces({ filters: { monitor: { id: 'mon_123', verdict: 'fail' } } }); Defensive patterns
Strategy: type-guard
Validate before calling
function assertMonitorFilter(filters) {
const monitor = filters?.monitor;
if (monitor === undefined) return;
if (monitor === null || typeof monitor !== 'object' || Array.isArray(monitor)) {
throw new Error('filter monitor must be an object: { id, verdict }');
}
if (typeof monitor.id !== 'string' || !monitor.id.trim()) throw new Error('filter monitor.id is required');
if (!['pass', 'fail', 'error'].includes(monitor.verdict)) throw new Error('invalid monitor.verdict');
} Type guard
function isMonitorFilter(v) {
return typeof v === 'object' && v !== null && !Array.isArray(v)
&& typeof v.id === 'string' && v.id.trim() !== ''
&& ['pass', 'fail', 'error'].includes(v.verdict);
} Try / catch
try {
await searchTraces({ filters });
} catch (error) {
if (error.message === 'filter monitor must be an object') {
filters.monitor = { id: String(filters.monitor), verdict: 'fail' };
}
} Prevention
- Always pass monitor as { id, verdict }, never a bare id string
- Validate the monitor shape before the tool call
- Omit the monitor key when not filtering by monitor
- Type monitor filters explicitly instead of unknown/string
When it happens
Trigger: Passing filters: { monitor: null }, { monitor: [] }, { monitor: 'monitor-1' }, or any non-object value for the monitor key in trace search filters.
Common situations: Passing just the monitor id string instead of an object; JSON arrays of monitor criteria; null where an object was expected after a failed lookup.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- filter must be a boolean
- filters must be an object
- filter must be a finite number
- filter must be a non-empty array of non-empty strings
- filter status_class values must be 2xx, 4xx, or 5xx
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/4498c2c146a5a589.
Report an issue: GitHub.
Appendix: source
Thrown at packages/cli/src/agent-mcp.ts:490
throw new Error(`filter ${key} must be a non-empty array of non-empty strings`);
}
if (key === "status_class" && value.some((entry) => !["2xx", "4xx", "5xx"].includes(entry as string))) {
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);View on GitHub (pinned to 3ee70a1026)