ComposioHQ/composio · error · Error
experimental_subAgent() requires Zod 4 with z.toJSONSchema()
Error message
experimental_subAgent() requires Zod 4 with z.toJSONSchema() when using options.schema.
What it means
When you pass a Zod schema via options.schema, the CLI must convert it to JSON Schema using z.toJSONSchema(), which only exists in Zod 4. If the installed Zod runtime lacks z.toJSONSchema, this error is thrown during option normalization.
Source
Thrown at ts/packages/cli/src/services/run-helpers-runtime.ts:370
}
const requestedTarget = options.target;
if (
requestedTarget !== undefined &&
requestedTarget !== 'claude' &&
requestedTarget !== 'codex' &&
requestedTarget !== 'user'
) {
throw new Error(
'experimental_subAgent() target must be "claude", "codex", or "user" when provided.'
);
}
const inputSchema = options.schema ?? options.jsonSchema;
let structuredSchema: Record<string, unknown> | undefined;
let zodSchema: z.ZodType | undefined;
if (inputSchema !== undefined) {
if (inputSchema instanceof z.ZodType) {
if (typeof z.toJSONSchema !== 'function') {
throw new Error(
'experimental_subAgent() requires Zod 4 with z.toJSONSchema() when using options.schema.'
);
}
zodSchema = inputSchema;
const generatedSchema = z.toJSONSchema(inputSchema);
structuredSchema = Schema.decodeUnknownSync(JsonObject)(generatedSchema);
} else if (Predicate.isRecord(inputSchema)) {
structuredSchema = inputSchema;
} else {
throw new Error('experimental_subAgent() schema must be a Zod schema or JSON Schema object.');
}
}
return {
...(requestedTarget === undefined ? {} : { target: requestedTarget }),
...(typeof options.model === 'string' ? { model: options.model } : {}),
...(options.schema === undefined ? {} : { schema: options.schema }),
...(options.jsonSchema === undefined ? {} : { jsonSchema: options.jsonSchema }),
...(structuredSchema === undefined ? {} : { structuredSchema }),View on GitHub (pinned to 64b1b85502)
Solutions
- Upgrade zod to v4 (pnpm add zod@^4) so z.toJSONSchema exists
- Alternatively pass options.jsonSchema with a plain JSON Schema object instead of a Zod schema
- Check for duplicate zod installs (pnpm why zod) and dedupe so the schema instance and the CLI share Zod 4
Example fix
// before
import { z } from 'zod'; // zod@3
await experimental_subAgent('p', { schema: z.object({ n: z.number() }) });
// after
pnpm add zod@^4
// or bypass Zod:
await experimental_subAgent('p', { jsonSchema: { type: 'object', properties: { n: { type: 'number' } } } }); Defensive patterns
Strategy: validation
Validate before calling
import { z } from 'zod';
if (opts.schema instanceof z.ZodType && typeof z.toJSONSchema !== 'function') {
throw new Error('Zod 4 required; use options.jsonSchema instead');
} Type guard
const hasToJsonSchema = (zz: typeof z): zz is typeof z & { toJSONSchema: (s: z.ZodType) => unknown } => typeof zz.toJSONSchema === 'function'; Try / catch
catch (e) { if (e instanceof Error && e.message.includes('Zod 4')) { /* fall back to jsonSchema option */ } } Prevention
- Pin zod@^4 in package.json
- Run pnpm why zod to detect duplicates
- Prefer plain JSON Schema when the runtime zod version is unknown
When it happens
Trigger: Calling experimental_subAgent(prompt, { schema: z.object({...}) }) while the resolved zod package in the CLI runtime is Zod 3 (which has no toJSONSchema).
Common situations: A project pinned to zod@^3, or a duplicate zod install where the schema instance comes from Zod 3 while the CLI expects Zod 4; upgrading the CLI but not zod, or vice versa.
Related errors
- experimental_subAgent() schema must be a Zod schema or JSON
- experimental_subAgent() structured output failed schema vali
- Failed to parse MCP server instance
- experimental_subAgent() target must be "claude", "codex", or
- experimental_subAgent() could not determine an agent CLI. Cu
AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28).
Data as JSON: /api/errors/7bfcd96076eb6c74.
Report an issue: GitHub.