colinhacks/zod · error · Error
Conditional schemas (if/then/else) are not supported
Error message
Conditional schemas (if/then/else) are not supported
What it means
Thrown by convertBaseSchema when the input contains any of `if`, `then`, or `else`. Conditional schema selection is a runtime branching construct with no direct Zod equivalent; the converter refuses rather than guessing an approximation.
Source
Thrown at packages/zod/src/v4/classic/from-json-schema.ts:162
}
function convertBaseSchema(schema: JSONSchema.JSONSchema, ctx: ConversionContext): ZodType {
// Handle unsupported features
if (schema.not !== undefined) {
// Special case: { not: {} } represents never
if (typeof schema.not === "object" && Object.keys(schema.not).length === 0) {
return z.never();
}
throw new Error("not is not supported in Zod (except { not: {} } for never)");
}
if (schema.unevaluatedItems !== undefined) {
throw new Error("unevaluatedItems is not supported");
}
if (schema.unevaluatedProperties !== undefined) {
throw new Error("unevaluatedProperties is not supported");
}
if (schema.if !== undefined || schema.then !== undefined || schema.else !== undefined) {
throw new Error("Conditional schemas (if/then/else) are not supported");
}
if (schema.dependentSchemas !== undefined || schema.dependentRequired !== undefined) {
throw new Error("dependentSchemas and dependentRequired are not supported");
}
// Handle $ref
if (schema.$ref) {
const refPath = schema.$ref;
if (ctx.refs.has(refPath)) {
return ctx.refs.get(refPath)!;
}
if (ctx.processing.has(refPath)) {
// Circular reference - use lazy
return z.lazy(() => {
if (!ctx.refs.has(refPath)) {
throw new Error(`Circular reference not resolved: ${refPath}`);
}View on GitHub (pinned to 912f0f51b0)
Solutions
- Re-model the conditional as a discriminated union: split into one object per branch and select by the discriminator value.
- Move the conditional logic into a post-conversion `.refine()` / `.superRefine()` on the resulting Zod schema.
- Inline the branches into separate `$defs` and let the caller pick the appropriate schema.
Example fix
// before
{
"if": { "properties": { "kind": { "const": "a" } }, "required": ["kind"] },
"then": { "properties": { "a": { "type": "string" } } },
"else": { "properties": { "b": { "type": "number" } } }
}
// after (build a discriminated union instead)
z.discriminatedUnion('kind', [
z.object({ kind: z.literal('a'), a: z.string() }),
z.object({ kind: z.literal('b'), b: z.number() }),
]); Defensive patterns
Strategy: fallback
Validate before calling
function hasConditional(schema: any): boolean {
return schema?.if !== undefined || schema?.then !== undefined || schema?.else !== undefined;
} Prevention
- Re-author if/then/else as discriminated unions before conversion.
- Apply conditional rules via refine/superRefine on the resulting schema.
- Maintain a mapping of unsupported keywords and their Zod workarounds.
When it happens
Trigger: Schemas using `if/then/else` to apply constraints conditionally, e.g. `{ if: { properties: { kind: { const: 'a' } } }, then: { ... }, else: { ... } }`.
Common situations: Polymorphic API schemas; JSON Schemas authored for full validators (Ajv); legacy draft-7 schemas migrating to Zod.
Related errors
- not is not supported in Zod (except { not: {} } for never)
- unevaluatedItems is not supported
- unevaluatedProperties is not supported
- dependentSchemas and dependentRequired are not supported
- Unsupported type: ${type}
AI-assisted analysis of colinhacks/zod@912f0f51b0 (2026-08-03).
Data as JSON: /data/errors/785e4af02fa947b7.json.
Report an issue: GitHub.