colinhacks/zod · error · Error

Symbols cannot be represented in JSON Schema

Error message

Symbols cannot be represented in JSON Schema

What it means

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"`.

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 912f0f51b0)

Solutions

  1. Call `z.toJSONSchema(schema, { unrepresentable: "any" })` to emit an empty schema for symbol nodes.
  2. Drop or replace the symbol field with a string enum before conversion if the contract needs to be concrete.
  3. Split the symbol field out of the converted subtree and document it separately.

Example fix

// before
z.toJSONSchema(z.object({ tag: z.symbol() })); // throws
// after
z.toJSONSchema(z.object({ tag: z.symbol() }), { unrepresentable: "any" });
Defensive patterns

Strategy: fallback

Validate before calling

const json = z.toJSONSchema(schema, { unrepresentable: "any" });

Type guard

function usesSymbol(schema: z.ZodType): boolean {
  return schema._zod.traits.has("$ZodSymbol");
}

Try / catch

try {
  return z.toJSONSchema(schema);
} catch (e) {
  if (e instanceof Error && /cannot be represented in JSON Schema/.test(e.message)) {
    return z.toJSONSchema(schema, { unrepresentable: "any" });
  }
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: Generating docs/contracts for a schema that includes symbol-typed fields; converting a meta-schema that uses symbols as opaque tokens.

Related errors


AI-assisted analysis of colinhacks/zod@912f0f51b0 (2026-08-03). Data as JSON: /data/errors/05a50cbb8b81626b.json. Report an issue: GitHub.