{"id":"785e4af02fa947b7","repo":"colinhacks/zod","slug":"conditional-schemas-if-then-else-are-not-support","errorCode":null,"errorMessage":"Conditional schemas (if/then/else) are not supported","messagePattern":"Conditional schemas \\(if/then/else\\) are not supported","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/zod/src/v4/classic/from-json-schema.ts","lineNumber":162,"sourceCode":"}\n\nfunction convertBaseSchema(schema: JSONSchema.JSONSchema, ctx: ConversionContext): ZodType {\n  // Handle unsupported features\n  if (schema.not !== undefined) {\n    // Special case: { not: {} } represents never\n    if (typeof schema.not === \"object\" && Object.keys(schema.not).length === 0) {\n      return z.never();\n    }\n    throw new Error(\"not is not supported in Zod (except { not: {} } for never)\");\n  }\n  if (schema.unevaluatedItems !== undefined) {\n    throw new Error(\"unevaluatedItems is not supported\");\n  }\n  if (schema.unevaluatedProperties !== undefined) {\n    throw new Error(\"unevaluatedProperties is not supported\");\n  }\n  if (schema.if !== undefined || schema.then !== undefined || schema.else !== undefined) {\n    throw new Error(\"Conditional schemas (if/then/else) are not supported\");\n  }\n  if (schema.dependentSchemas !== undefined || schema.dependentRequired !== undefined) {\n    throw new Error(\"dependentSchemas and dependentRequired are not supported\");\n  }\n\n  // Handle $ref\n  if (schema.$ref) {\n    const refPath = schema.$ref;\n    if (ctx.refs.has(refPath)) {\n      return ctx.refs.get(refPath)!;\n    }\n\n    if (ctx.processing.has(refPath)) {\n      // Circular reference - use lazy\n      return z.lazy(() => {\n        if (!ctx.refs.has(refPath)) {\n          throw new Error(`Circular reference not resolved: ${refPath}`);\n        }","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/colinhacks/zod/blob/912f0f51b0ced654d0069741e7160834dca742ee/packages/zod/src/v4/classic/from-json-schema.ts#L144-L180","documentation":"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.","triggerScenarios":"Schemas using `if/then/else` to apply constraints conditionally, e.g. `{ if: { properties: { kind: { const: 'a' } } }, then: { ... }, else: { ... } }`.","commonSituations":"Polymorphic API schemas; JSON Schemas authored for full validators (Ajv); legacy draft-7 schemas migrating to Zod.","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."],"exampleFix":"// before\n{\n  \"if\":   { \"properties\": { \"kind\": { \"const\": \"a\" } }, \"required\": [\"kind\"] },\n  \"then\": { \"properties\": { \"a\": { \"type\": \"string\" } } },\n  \"else\": { \"properties\": { \"b\": { \"type\": \"number\" } } }\n}\n\n// after (build a discriminated union instead)\nz.discriminatedUnion('kind', [\n  z.object({ kind: z.literal('a'), a: z.string() }),\n  z.object({ kind: z.literal('b'), b: z.number() }),\n]);","handlingStrategy":"fallback","validationCode":"function hasConditional(schema: any): boolean {\n  return schema?.if !== undefined || schema?.then !== undefined || schema?.else !== undefined;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["json-schema","if-then-else","conditional","unsupported","v4","from-json-schema"],"analyzedSha":"912f0f51b0ced654d0069741e7160834dca742ee","analyzedAt":"2026-08-03T17:41:55.908Z","schemaVersion":2}