colinhacks/zod · error · Error
BigInt literals cannot be represented in JSON Schema
Error message
BigInt literals cannot be represented in JSON Schema
What it means
In `literalProcessor` (json-schema-processors.ts:173), a literal value whose `typeof` is `"bigint"` cannot be encoded in JSON. With `ctx.unrepresentable === "throw"` (default) it throws; with `unrepresentable: "any"` it falls back to `vals.push(Number(val))` (coerces to a number, losing precision for large values).
Source
Thrown at packages/zod/src/v4/core/json-schema-processors.ts:175
// 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);
if (ctx.target === "draft-04" || ctx.target === "openapi-3.0") {
json.enum = [val];
} else {
json.const = val;
}
} else {View on GitHub (pinned to 912f0f51b0)
Solutions
- Pass `{ unrepresentable: "any" }` (note: large bigints will be lossy via `Number()`).
- Replace the bigint literal with a string literal (`z.literal("5")`) and convert at the boundary to preserve precision.
- Use a string regex schema (`z.string().regex(/^\d+$/)`) instead of a bigint literal for the contract.
Example fix
// before
z.toJSONSchema(z.literal(BigInt(5))); // throws
// after
z.toJSONSchema(z.literal("5")); // -> { type: "string", const: "5" } Defensive patterns
Strategy: fallback
Validate before calling
// For lossless contracts, encode bigints as string literals.
const contractSchema = z.literal("5");
const json = z.toJSONSchema(contractSchema);
// Or opt into lossy numeric coercion:
// z.toJSONSchema(schema, { unrepresentable: "any" }); Type guard
function hasBigIntLiteral(s: z.ZodLiteral<any>): boolean {
return [...s.values].some((v) => typeof v === "bigint");
} 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
- Prefer string literals over bigint literals in schemas destined for JSON Schema (preserves precision).
- Be aware that `unrepresentable: "any"` coerces bigints via `Number()`, which is lossy for large values.
- Keep bigint literals in runtime-only schemas separate from contract schemas.
When it happens
Trigger: `z.toJSONSchema()` over `z.literal(BigInt(5))` or `z.literal([1n, 2n])`, with default options.
Common situations: Using bigint literals for IDs/bitmasks and then generating a contract; converting schemas built from database bigint constants.
Related errors
- BigInt cannot be represented in JSON Schema
- Literal `undefined` cannot be represented in JSON Schema
- Symbols cannot be represented in JSON Schema
- Undefined 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/75c2c37fd6f5c60f.json.
Report an issue: GitHub.