JuliusBrussee/caveman · error
sort has unknown key(s)
Error message
sort has unknown key(s): ${unknown.sort().join(", ")} What it means
When `sort` is provided as an object, only the keys `by` and `dir` are allowed. validateTraceSearch collects any other keys and throws this error listing them sorted, mirroring the monitor-filter whitelist pattern.
Solutions
- Keep only `by` and `dir` in the sort object; delete other keys.
- Fix typos: `by` for the field, `dir` for the direction.
- Use allowed `by` values: timestamp, total_cost_usd, latency_ms, total_tokens (see related enum error).
- Explicitly construct the sort object rather than spreading a generic config.
Example fix
// before
{ "sort": { "by": "latency_ms", "dir": "desc", "nulls": "last" } }
// after
{ "sort": { "by": "latency_ms", "dir": "desc" } } Defensive patterns
Strategy: validation
Validate before calling
const SORT_KEYS = new Set(["by", "dir"]);
if (args.sort && Object.keys(args.sort).some(k => !SORT_KEYS.has(k)))
throw new Error("sort may only contain by and dir"); Type guard
function isValidSort(s) {
return isPlainObject(s) && Object.keys(s).every(k => k === "by" || k === "dir");
} Try / catch
try {
await traceSearch(args);
} catch (e) {
if (e.message.startsWith("sort has unknown key")) {
args.sort = { by: args.sort.by, dir: args.sort.dir };
return traceSearch(args);
}
throw e;
} Prevention
- Construct sort objects explicitly; avoid spreading generic sort configs.
- Keep field names in sync with API version updates (dir vs order).
- Type the sort shape in client code so extra keys fail at compile time.
When it happens
Trigger: trace_search with {"sort":{"by":"latency_ms","field":"x"}}, {"sort":{"key":"timestamp"}}, or typos like {"sort":{"order":"asc"}} instead of "dir".
Common situations: Renamed fields across API versions (order vs dir); extra options like nulls-handling copied from other sort DSLs; typo of `dir`/`by`; accidental spread of a larger sort config object.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- cursor has unknown key(s)
- filter monitor has unknown key(s)
- pending transaction is malformed; refusing recovery
- sort must be an object
- canonical span
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/594fcf08a977c93d.
Report an issue: GitHub.
Appendix: source
Thrown at packages/cli/src/agent-mcp.ts:523
}
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");
const unknown = Object.keys(sort).filter((key) => key !== "by" && key !== "dir");
if (unknown.length > 0) throw new Error(`sort has unknown key(s): ${unknown.sort().join(", ")}`);
optionalEnum(sort, "by", ["timestamp", "total_cost_usd", "latency_ms", "total_tokens"]);
optionalEnum(sort, "dir", ["asc", "desc"]);
}
const cursor = args.cursor;
if (cursor !== undefined) {
if (!cursor || typeof cursor !== "object" || Array.isArray(cursor)) throw new Error("cursor must be an object");
const unknown = Object.keys(cursor).filter((key) => key !== "sort_value" && key !== "request_id" && key !== "group_key");
if (unknown.length > 0) throw new Error(`cursor has unknown key(s): ${unknown.sort().join(", ")}`);
if (typeof cursor.sort_value !== "string" || cursor.sort_value === "") throw new Error("cursor.sort_value is required");
for (const key of ["request_id", "group_key"]) {
if (cursor[key] !== undefined && typeof cursor[key] !== "string") throw new Error(`cursor.${key} must be a string`);
}
}
}
async function callTool(client: AgentMcpClient, name: string, rawArgs: unknown): Promise<ToolResult> {
const started = Date.now();
let outcome: "ok" | "error" = "ok";View on GitHub (pinned to 3ee70a1026)