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

  1. Inspect the transform that produced the segment and ensure it emits { name, description, input } with correct types.
  2. Add the missing description/input fields to the tool definition that feeds the transform.
  3. Log the raw transform output before validation to see what actually came out.
  4. 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

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


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)