{"record":{"id":"cd230833f43c8cf6","repo":"JuliusBrussee/caveman","slug":"key-is-required","errorCode":null,"errorMessage":"${key} is required","messagePattern":"(.+?) is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/cli/src/agent-mcp.ts","lineNumber":410,"sourceCode":"\nfunction metadataOnlyTrace(trace: JSONValue): JSONObject {\n  return allowlistedObject(trace, AGENT_TRACE_FIELDS);\n}\n\nfunction metadataOnlySpans(value: JSONValue): JSONObject {\n  if (!value || typeof value !== \"object\" || Array.isArray(value)) return { spans: [], timeline: [] };\n  const spans = Array.isArray(value.spans)\n    ? value.spans.map((span) => allowlistedObject(span, AGENT_SPAN_FIELDS))\n    : [];\n  const timeline = Array.isArray(value.timeline)\n    ? value.timeline.map((event) => allowlistedObject(event, AGENT_TIMELINE_FIELDS))\n    : [];\n  return { spans, timeline };\n}\n\nfunction stringArg(args: JSONObject, key: string): string {\n  const value = args[key];\n  if (typeof value !== \"string\" || value.trim() === \"\") throw new Error(`${key} is required`);\n  return value;\n}\n\nfunction result(value: JSONValue): ToolResult {\n  const structuredContent = value && typeof value === \"object\" && !Array.isArray(value)\n    ? value as JSONObject\n    : { value };\n  return {\n    content: [{ type: \"text\", text: JSON.stringify(structuredContent) }],\n    structuredContent,\n  };\n}\n\nfunction errorResult(error: unknown): ToolResult {\n  const candidate = error as { message?: unknown; code?: unknown; status?: unknown };\n  const structuredContent: JSONObject = {\n    error: typeof candidate.code === \"string\" ? candidate.code : \"cave_agent_tool_failed\",\n    message: typeof candidate.message === \"string\" ? candidate.message : \"Caveman tool failed.\",","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/cli/src/agent-mcp.ts#L392-L428","documentation":"stringArg() in the CLI's MCP tool layer (packages/cli/src/agent-mcp.ts) throws when a required string argument is absent, not a string, or whitespace-only. It backs tools like caveman_report (report), caveman_trace_get (trace_id), and caveman_experiment_get (action, experiment_id), so the MCP client sees an isError result naming the missing key.","triggerScenarios":"Calling caveman_trace_get without trace_id; passing trace_id as a number; sending \"\" or \"   \" for report/action/experiment_id; an LLM omitting the argument in its tool-call JSON.","commonSituations":"A model-generated tool call drops a required field; a client sends numeric ids (e.g. 12345 instead of \"12345\"); copy-paste payloads trimmed to placeholders.","solutions":["Supply the named argument as a non-empty string (e.g. {\"trace_id\": \"abc123\"}).","Stringify numeric ids before calling: String(experimentId).","Define the argument as required in your MCP client's tool schema so the model cannot omit it."],"exampleFix":"// before\ncallTool(\"caveman_trace_get\", {})\n\n// after\ncallTool(\"caveman_trace_get\", { trace_id: \"01J8Z...\" })","handlingStrategy":"validation","validationCode":"function requireStringArg(args: Record<string, unknown>, key: string): string {\n  const v = args[key];\n  if (typeof v !== \"string\" || v.trim() === \"\") throw new Error(`${key} is required`);\n  return v;\n}\n// before calling caveman_trace_get / caveman_report / caveman_experiment_get:\nrequireStringArg(args, \"trace_id\");","typeGuard":"function isNonEmptyString(v: unknown): v is string {\n  return typeof v === \"string\" && v.trim() !== \"\";\n}","tryCatchPattern":"try { await client.callTool(\"caveman_trace_get\", args); } catch (e) { if (e instanceof Error && /is required$/.test(e.message)) { /* prompt for the missing arg, do not retry unchanged */ } throw e; }","preventionTips":["Declare required string args in your MCP client schema.","Stringify ids at the boundary; never pass numbers where ids are expected.","Check the error message for the exact key name it names."],"tags":["mcp","validation","arguments","cli"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}