{"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":"error","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/3ee70a102609e550bd2e68004bf5990a9341c851/packages/cli/src/agent-mcp.ts#L392-L428","documentation":"stringArg is the agent-MCP tool layer's argument validator: it asserts that args[key] exists, is a string, and is non-empty after trimming. Handlers for commands like report, trace, and actions call it to extract mandatory identifiers. It throws `${key} is required` when the argument is missing, of the wrong type, or whitespace-only.","triggerScenarios":"Calling the MCP tools report, trace (traceId), or an action requiring action/experimentId without that key in args, with a non-string value (number/null/object), or with an empty/whitespace string.","commonSituations":"MCP client omitting a required tool argument; passing a numeric id as a JSON number instead of a string; passing null; an LLM generating tool calls that drop required params; whitespace-only values from copy/paste.","solutions":["Add the required argument as a non-empty string to the tool call arguments","Coerce numeric/other ids to string before invoking (String(id))","Check the tool's input schema for the exact required key names (report's id, trace's traceId, etc.)","Trim user-supplied input to ensure it isn't blank"],"exampleFix":"// before\ncallTool('report', { format: 'json' }); // missing id\ncallTool('report', { id: 42 });\n// after\ncallTool('report', { format: 'json', id: '42' });","handlingStrategy":"validation","validationCode":"function requireString(args, key) {\n  const v = args[key];\n  if (typeof v !== 'string' || v.trim() === '') throw new Error(`${key} is required`);\n  return v;\n}\n// call before invoking the tool: requireString(args, 'traceId')","typeGuard":"function isNonEmptyString(v) {\n  return typeof v === 'string' && v.trim().length > 0;\n}","tryCatchPattern":"try {\n  await callTool('trace', { traceId });\n} catch (error) {\n  if (error.message.endsWith('is required')) {\n    // prompt user/model for the missing argument and retry\n  }\n}","preventionTips":["Read each tool's input schema and always supply required keys","Coerce ids to strings before sending (String(id))","Validate tool-call arguments with a schema validator (zod/ajv) before dispatching","Trim inputs; reject blank strings at the source (UI or client)"],"tags":["mcp","validation","arguments"],"backgroundTag":"missing-required-argument","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}