JuliusBrussee/caveman · error
must be one of
Error message
${key} must be one of ${values.join(", ")} What it means
optionalEnum validates that an optional top-level argument is either omitted or a string from a fixed set. validateTraceSearch uses it for `date_field` (occurred|updated) and `group_by` (session|workflow|model|member). Passing a non-string or an out-of-set value throws this error naming the key and the allowed values.
Solutions
- Use exactly one of the allowed values shown in the message: date_field = occurred|updated, group_by = session|workflow|model|member.
- Remove the argument entirely if you don't need it (both are optional).
- Fix casing — values are lowercase and case-sensitive.
- Validate against the tool's input schema before sending.
Example fix
// before
{ "group_by": "agent" }
// after
{ "group_by": "model" } Defensive patterns
Strategy: validation
Validate before calling
const DATE_FIELDS = ["occurred", "updated"];
const GROUP_BYS = ["session", "workflow", "model", "member"];
if (args.date_field !== undefined && !DATE_FIELDS.includes(args.date_field))
throw new Error(`date_field must be one of ${DATE_FIELDS.join(", ")}`);
if (args.group_by !== undefined && !GROUP_BYS.includes(args.group_by))
throw new Error(`group_by must be one of ${GROUP_BYS.join(", ")}`); Type guard
function isOptionalEnum(v, values) {
return v === undefined || (typeof v === "string" && values.includes(v));
} Try / catch
try {
await traceSearch(args);
} catch (e) {
const m = e.message.match(/^(\w+) must be one of (.+)$/);
if (m) throw new Error(`Fix ${m[1]}: allowed values are ${m[2]}`);
throw e;
} Prevention
- Keep the allowed enum lists in shared constants next to the call site.
- Only set the argument when you have a valid value (they are optional).
- Validate option values at config-load time, not request time.
When it happens
Trigger: trace_search with {"date_field":"created"} (not allowed), {"group_by":"agent"} (invalid), {"group_by":123} (non-string), or {"date_field":null} treated as a defined non-string value only if not undefined.
Common situations: Guessing enum values instead of reading the tool schema; mixing up date_field options with other APIs' field names (e.g. "created_at"); group_by values copied from a different reporting endpoint.
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.verdict must be pass, fail, or error
- filter status_class values must be 2xx, 4xx, or 5xx
- is required
- assembly slot has unknown stability
- assembly slot has unknown stability
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/9705716c1025b87d.
Report an issue: GitHub.
Appendix: source
Thrown at packages/cli/src/agent-mcp.ts:503
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"]);
optionalEnum(args, "group_by", ["session", "workflow", "model", "member"]);
const pageSize = args.page_size;
if (pageSize !== undefined && (!Number.isSafeInteger(pageSize) || (pageSize as number) < 1 || (pageSize as number) > 500)) {
throw new Error("page_size must be an integer from 1 to 500");
}
const sort = args.sort;
if (sort !== undefined) {
if (!sort || typeof sort !== "object" || Array.isArray(sort)) throw new Error("sort must be an object");View on GitHub (pinned to 3ee70a1026)