{"id":"05a50cbb8b81626b","repo":"colinhacks/zod","slug":"symbols-cannot-be-represented-in-json-schema","errorCode":null,"errorMessage":"Symbols cannot be represented in JSON Schema","messagePattern":"Symbols cannot be represented in JSON Schema","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/zod/src/v4/core/json-schema-processors.ts","lineNumber":110,"sourceCode":"    json.maximum = maximum;\n  }\n\n  if (typeof multipleOf === \"number\") json.multipleOf = multipleOf;\n};\n\nexport const booleanProcessor: Processor<schemas.$ZodBoolean> = (_schema, _ctx, json, _params) => {\n  (json as JSONSchema.BooleanSchema).type = \"boolean\";\n};\n\nexport const bigintProcessor: Processor<schemas.$ZodBigInt> = (_schema, ctx, _json, _params) => {\n  if (ctx.unrepresentable === \"throw\") {\n    throw new Error(\"BigInt cannot be represented in JSON Schema\");\n  }\n};\n\nexport const symbolProcessor: Processor<schemas.$ZodSymbol> = (_schema, ctx, _json, _params) => {\n  if (ctx.unrepresentable === \"throw\") {\n    throw new Error(\"Symbols cannot be represented in JSON Schema\");\n  }\n};\n\nexport const nullProcessor: Processor<schemas.$ZodNull> = (_schema, ctx, json, _params) => {\n  if (ctx.target === \"openapi-3.0\") {\n    json.type = \"string\";\n    json.nullable = true;\n    json.enum = [null];\n  } else {\n    json.type = \"null\";\n  }\n};\n\nexport const undefinedProcessor: Processor<schemas.$ZodUndefined> = (_schema, ctx, _json, _params) => {\n  if (ctx.unrepresentable === \"throw\") {\n    throw new Error(\"Undefined cannot be represented in JSON Schema\");\n  }\n};","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/colinhacks/zod/blob/912f0f51b0ced654d0069741e7160834dca742ee/packages/zod/src/v4/core/json-schema-processors.ts#L92-L128","documentation":"Symbols have no JSON serialization and therefore no JSON Schema type, so `symbolProcessor` (json-schema-processors.ts:108) refuses `z.symbol()`. Like the other unrepresentable processors, it throws only when `ctx.unrepresentable === \"throw\"` (the default) and is silenced by `unrepresentable: \"any\"`.","triggerScenarios":"Running `z.toJSONSchema()` over a schema containing `z.symbol()`, with default options. Common when a schema reuses a symbol field as a discriminator or sentinel.","commonSituations":"Generating docs/contracts for a schema that includes symbol-typed fields; converting a meta-schema that uses symbols as opaque tokens.","solutions":["Call `z.toJSONSchema(schema, { unrepresentable: \"any\" })` to emit an empty schema for symbol nodes.","Drop or replace the symbol field with a string enum before conversion if the contract needs to be concrete.","Split the symbol field out of the converted subtree and document it separately."],"exampleFix":"// before\nz.toJSONSchema(z.object({ tag: z.symbol() })); // throws\n// after\nz.toJSONSchema(z.object({ tag: z.symbol() }), { unrepresentable: \"any\" });","handlingStrategy":"fallback","validationCode":"const json = z.toJSONSchema(schema, { unrepresentable: \"any\" });","typeGuard":"function usesSymbol(schema: z.ZodType): boolean {\n  return schema._zod.traits.has(\"$ZodSymbol\");\n}","tryCatchPattern":"try {\n  return z.toJSONSchema(schema);\n} catch (e) {\n  if (e instanceof Error && /cannot be represented in JSON Schema/.test(e.message)) {\n    return z.toJSONSchema(schema, { unrepresentable: \"any\" });\n  }\n  throw e;\n}","preventionTips":["Avoid symbol-typed fields in schemas you intend to convert to JSON Schema.","Reserve symbols for internal/runtime-only metadata, not contract fields.","Standardize on `{ unrepresentable: \"any\" }` for heterogeneous schemas."],"tags":["json-schema","symbol","unrepresentable","openapi"],"analyzedSha":"912f0f51b0ced654d0069741e7160834dca742ee","analyzedAt":"2026-08-03T17:41:55.908Z","schemaVersion":2}