{"record":{"id":"e90b1dc8b592853c","repo":"JuliusBrussee/caveman","slug":"cave-claude-tool-schema-unsupported","errorCode":"cave_claude_tool_schema_unsupported","errorMessage":"cave_claude_tool_schema_unsupported:${item.name}","messagePattern":"cave_claude_tool_schema_unsupported:(.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/agent/src/claude-runtime.ts","lineNumber":151,"sourceCode":"    // lane can only ever be an unlocked run: a missing gateway degrades to\n    // observe-only rather than blocking a first response.\n    const { useGateway } = await resolveCaveRoute(gatewayURL, options, false);\n    const instructions = assembleSystemPrompt(definition, lowered);\n    const runID = crypto.randomUUID();\n    const sessionID = `claude-${definition.id}-${runID}`;\n    const prefixSHA256 = sha256(stableStringify({\n      instructions,\n      tools: definition.tools.map((item) => ({\n        name: item.name,\n        description: item.description,\n        input: item.input,\n      })),\n    }));\n    const toolNames = new Set<string>();\n    const mcpTools = definition.tools.map((item) => {\n      const converted = z.fromJSONSchema(item.input as Record<string, unknown>);\n      if (!(converted instanceof z.ZodObject)) {\n        throw new Error(`cave_claude_tool_schema_unsupported:${item.name}`);\n      }\n      const execute = createHarnessToolExecutor({\n        definition,\n        tool: item,\n        sandbox,\n        ...(options.sandboxProfile === undefined ? {} : { sandboxProfile: options.sandboxProfile }),\n        ...(options.engineBin === undefined ? {} : { engineBin: options.engineBin }),\n      });\n      const wireName = `mcp__caveman_agent__${item.name}`;\n      toolNames.add(wireName);\n      return claudeTool(\n        item.name,\n        item.description,\n        converted.shape,\n        async (args) => {\n          const value = await execute(args, controller.signal);\n          if (!isRecord(value) || !Array.isArray(value.content)) {\n            throw new Error(`cave_claude_tool_result_invalid:${item.name}`);","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/agent/src/claude-runtime.ts#L133-L169","documentation":"Each tool's JSON-Schema input must be convertible by z.fromJSONSchema into a z.ZodObject. Schemas that convert to another Zod type (e.g. a bare array, string, or anyOf at the top level) are rejected, with the tool name appended to the message.","triggerScenarios":"Declaring a tool whose input JSON schema's top level is not an object — e.g. {\"type\":\"array\"}, {\"type\":\"string\"}, or an anyOf/oneOf at the root.","commonSituations":"Hand-writing tool schemas copied from OpenAI-style function definitions where parameters wrap differently; generating schemas from a serializer that emits non-object roots.","solutions":["Wrap the schema in an object type: {\"type\":\"object\",\"properties\":{...},\"required\":[...] }","Move list inputs under a named property (e.g. {\"items\": {...}} becomes {\"type\":\"object\",\"properties\":{\"items\":...}})","Simplify the root schema so z.fromJSONSchema yields a ZodObject"],"exampleFix":"// before\ninput: { type: \"array\", items: { type: \"string\" } }\n// after\ninput: { type: \"object\", properties: { values: { type: \"array\", items: { type: \"string\" } } }, required: [\"values\"] }","handlingStrategy":"validation","validationCode":"for (const t of definition.tools) {\n  const conv = z.fromJSONSchema(t.input);\n  if (!(conv instanceof z.ZodObject)) throw new Error(`tool ${t.name} input schema must be a top-level object`);\n}","typeGuard":"const isObjectSchema = (t) => t.input?.type === \"object\";","tryCatchPattern":"try { await runClaudeAgent(opts); } catch (e) { if (String(e.message).startsWith(\"cave_claude_tool_schema_unsupported:\")) { /* fix that tool's schema and retry */ } throw e; }","preventionTips":["Always make tool input schemas top-level object types","Test-convert each schema with z.fromJSONSchema in unit tests","Avoid root-level anyOf/oneOf in tool schemas"],"tags":["tools","schema","zod","claude-runtime"],"backgroundTag":"schema-validation-failed","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"}