JuliusBrussee/caveman · error
tool_schema_transform_invalid
tool_schema_transform_invalid
Error message
tool_schema_transform_invalid:${segmentID} What it means
validatedToolSchemaBytes parses bytes produced by a schema transform and requires a record with string "name", string "description", and record "input". Anything else means the transform emitted an invalid tool schema, and the segment ID is included in the message to identify which tool failed.
Solutions
- Inspect the transform that produced the segment and ensure it emits { name, description, input } with correct types.
- Add the missing description/input fields to the tool definition that feeds the transform.
- Log the raw transform output before validation to see what actually came out.
- If using a third-party transform, check its version against the runtime's expected schema.
Example fix
// before: transform output missing description
JSON.stringify({ name: "search", input: searchSchema })
// after
JSON.stringify({ name: "search", description: "Search the index", input: searchSchema }) Defensive patterns
Strategy: type-guard
Validate before calling
function isValidTransformedSchema(v: unknown): boolean {
return !!v && typeof v === 'object' && typeof (v as any).name === 'string' &&
typeof (v as any).description === 'string' &&
!!(v as any).input && typeof (v as any).input === 'object';
} Type guard
const isRecord = (v: unknown): v is Record<string, unknown> => typeof v === 'object' && v !== null && !Array.isArray(v);
function validToolSchema(v: unknown): v is { name: string; description: string; input: Record<string, unknown> } {
return isRecord(v) && typeof v.name === 'string' && typeof v.description === 'string' && isRecord(v.input);
} Try / catch
try {
return validatedToolSchemaBytes(output, segmentID);
} catch (e) {
if (String(e?.message).startsWith('tool_schema_transform_invalid')) {
console.error(`transform for ${segmentID} emitted invalid schema`);
}
throw e;
} Prevention
- Unit-test every custom transform's output against the { name, description, input } shape.
- Never register tools without a description.
- Log raw transform output during schema development.
When it happens
Trigger: A schema transform output for segment segmentID fails JSON.parse or the parsed object lacks name:string, description:string, or a record-shaped input at runtime.ts:3804.
Common situations: A custom transform/plugin emitting the wrong shape; an upstream provider schema change; a tool registered without a description; transform output being truncated or double-encoded.
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
- cave_tool_schema_invalid
- agent conformance fixtures must cover claude and pi
- cave_transform_safety_mismatch
- cave_transform_trace_limit
- cave_unknown_transform
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/885966d469fd6196.
Report an issue: GitHub.
Appendix: source
Thrown at packages/agent/src/runtime.ts:3804
: "Use cave_retrieve for omitted detail.",
].join("\n"),
}],
details: {
effect: definition.effect,
resultPolicy: definition.result,
recoveryHandle: transformed.handle,
recoveryVerified: true,
},
};
},
};
}
function validatedToolSchemaBytes(output: Uint8Array, segmentID: string): Uint8Array {
const parsed = JSON.parse(new TextDecoder().decode(output)) as unknown;
if (!isRecord(parsed) || typeof parsed.name !== "string" ||
typeof parsed.description !== "string" || !isRecord(parsed.input)) {
throw new Error(`tool_schema_transform_invalid:${segmentID}`);
}
return output;
}
function providerToolDefinition(
definition: ToolDefinition,
lowered: LoweredContext,
appliedPlan: AppliedPlan,
): { description: string; input: TSchema } {
const segment = lowered.ir.segments.find((item) => item.id === `tool.${definition.name}`);
if (!segment) throw new Error(`cave_context_segment_missing:tool.${definition.name}`);
const body = appliedPlan.bodies.get(segment.bodyHandle);
if (!body) throw new Error(`cave_context_body_missing:tool.${definition.name}`);
const parsed = JSON.parse(new TextDecoder().decode(body)) as unknown;
if (!isRecord(parsed) || parsed.name !== definition.name ||
typeof parsed.description !== "string" || !isRecord(parsed.input)) {
throw new Error(`cave_tool_schema_invalid:${definition.name}`);
}View on GitHub (pinned to 3ee70a1026)