colinhacks/zod · error · Error
Symbols cannot be represented in JSON Schema
Error message
Symbols cannot be represented in JSON Schema
What it means
Thrown by toJSONSchema() when a ZodSymbol schema (z.symbol()) is encountered and unrepresentable is 'throw' (default). Symbols are a JavaScript runtime concept with no JSON or JSON Schema equivalent, so conversion is refused.
Solutions
- Pass { unrepresentable: 'any' } to toJSONSchema() so symbol fields become {}.
- Strip symbol fields from the schema used for JSON export; model the external contract with z.string() instead.
- Split the runtime schema from the export schema so symbols never reach toJSONSchema().
Example fix
// before (throws)
const Schema = z.object({ tag: z.symbol() });
z.toJSONSchema(Schema);
// after
const Schema = z.object({ tag: z.symbol() });
z.toJSONSchema(Schema, { unrepresentable: 'any' }); Defensive patterns
Strategy: try-catch
Validate before calling
const opts = schemaContains(schema, (s) => s._zod.def.type === 'symbol')
? { unrepresentable: 'any' }
: {};
const json = z.toJSONSchema(schema, opts); Type guard
function hasSymbol(schema) {
return schema._zod.def.type === 'symbol';
} Try / catch
try {
return z.toJSONSchema(schema);
} catch (e) {
if (e.message === 'Symbols cannot be represented in JSON Schema') {
return z.toJSONSchema(schema, { unrepresentable: 'any' });
}
throw e;
} Prevention
- Keep symbol fields in runtime-only schemas; strip them before JSON Schema export.
- Default to { unrepresentable: 'any' } for schemas that may carry opaque tokens.
- Maintain separate export schemas for external contracts.
When it happens
Trigger: Calling toJSONSchema() on a schema that contains z.symbol(), e.g. a model keyed by Symbol-valued discriminators. Exporting a registry that mixes symbol fields into its type.
Common situations: Internal schemas that use symbols as opaque tokens, then feeding the same schema to a JSON-Schema-based validator or doc generator.
Related errors
- BigInt cannot be represented in JSON Schema
- BigInt literals cannot be represented in JSON Schema
- Custom types cannot be represented in JSON Schema
- Date cannot be represented in JSON Schema
- Dynamic catch values are not supported in JSON Schema
AI-assisted analysis of colinhacks/zod@2d90846af9 (2026-08-11).
Data as JSON: /api/errors/05a50cbb8b81626b.
Report an issue: GitHub.
Appendix: source
Thrown at packages/zod/src/v4/core/json-schema-processors.ts:110
json.maximum = maximum;
}
if (typeof multipleOf === "number") json.multipleOf = multipleOf;
};
export const booleanProcessor: Processor<schemas.$ZodBoolean> = (_schema, _ctx, json, _params) => {
(json as JSONSchema.BooleanSchema).type = "boolean";
};
export const bigintProcessor: Processor<schemas.$ZodBigInt> = (_schema, ctx, _json, _params) => {
if (ctx.unrepresentable === "throw") {
throw new Error("BigInt cannot be represented in JSON Schema");
}
};
export const symbolProcessor: Processor<schemas.$ZodSymbol> = (_schema, ctx, _json, _params) => {
if (ctx.unrepresentable === "throw") {
throw new Error("Symbols cannot be represented in JSON Schema");
}
};
export const nullProcessor: Processor<schemas.$ZodNull> = (_schema, ctx, json, _params) => {
if (ctx.target === "openapi-3.0") {
json.type = "string";
json.nullable = true;
json.enum = [null];
} else {
json.type = "null";
}
};
export const undefinedProcessor: Processor<schemas.$ZodUndefined> = (_schema, ctx, _json, _params) => {
if (ctx.unrepresentable === "throw") {
throw new Error("Undefined cannot be represented in JSON Schema");
}
};View on GitHub (pinned to 2d90846af9)