colinhacks/zod · error · Error
Literal `undefined` cannot be represented in JSON Schema
Error message
Literal `undefined` cannot be represented in JSON Schema
What it means
Inside `literalProcessor` (json-schema-processors.ts:163), each literal value is inspected. A value of `undefined` is not representable, so when `ctx.unrepresentable === "throw"` the processor throws for `z.literal(undefined)`. With `unrepresentable: "any"` the undefined entry is silently dropped from the produced enum/const.
Source
Thrown at packages/zod/src/v4/core/json-schema-processors.ts:169
}
};
export const enumProcessor: Processor<schemas.$ZodEnum> = (schema, _ctx, json, _params) => {
const def = schema._zod.def as schemas.$ZodEnumDef;
const values = getEnumValues(def.entries);
// Number enums can have both string and number values
if (values.every((v) => typeof v === "number")) json.type = "number";
if (values.every((v) => typeof v === "string")) json.type = "string";
json.enum = values;
};
export const literalProcessor: Processor<schemas.$ZodLiteral> = (schema, ctx, json, _params) => {
const def = schema._zod.def as schemas.$ZodLiteralDef<any>;
const vals: (string | number | boolean | null)[] = [];
for (const val of def.values) {
if (val === undefined) {
if (ctx.unrepresentable === "throw") {
throw new Error("Literal `undefined` cannot be represented in JSON Schema");
} else {
// do not add to vals
}
} else if (typeof val === "bigint") {
if (ctx.unrepresentable === "throw") {
throw new Error("BigInt literals cannot be represented in JSON Schema");
} else {
vals.push(Number(val));
}
} else {
vals.push(val);
}
}
if (vals.length === 0) {
// do nothing (an undefined literal was stripped)
} else if (vals.length === 1) {
const val = vals[0]!;
json.type = val === null ? ("null" as const) : (typeof val as any);View on GitHub (pinned to 912f0f51b0)
Solutions
- Pass `{ unrepresentable: "any" }` so the undefined literal is omitted from the output.
- Replace `z.literal(undefined)` with `z.undefined().optional()` or model absence via optionality (`.optional()`).
- Filter undefined out of the literal array before constructing the schema.
Example fix
// before
z.toJSONSchema(z.literal(undefined)); // throws
// after
z.toJSONSchema(z.literal(undefined), { unrepresentable: "any" });
// or model it as an optional field instead of a literal Defensive patterns
Strategy: fallback
Validate before calling
const json = z.toJSONSchema(schema, { unrepresentable: "any" }); // undefined literal is dropped Type guard
function hasUndefinedLiteral(s: z.ZodLiteral<any>): boolean {
return [...s.values].some((v) => v === undefined);
} 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
- Filter `undefined` out of literal value arrays before constructing the schema.
- Model absence with `.optional()` instead of `z.literal(undefined)`.
- Use `{ unrepresentable: "any" }` when converting schemas that may include undefined literals.
When it happens
Trigger: `z.toJSONSchema()` over a schema containing `z.literal(undefined)`, or a multi-value `z.literal([x, undefined])`, with default options.
Common situations: Building a literal from a config value that happens to be undefined; unions of literals that include undefined to mean 'absent'.
Related errors
- Undefined cannot be represented in JSON Schema
- BigInt literals cannot be represented in JSON Schema
- BigInt cannot be represented in JSON Schema
- Symbols cannot be represented in JSON Schema
- Void cannot be represented in JSON Schema
AI-assisted analysis of colinhacks/zod@912f0f51b0 (2026-08-03).
Data as JSON: /data/errors/631f1e922a00d60b.json.
Report an issue: GitHub.