colinhacks/zod · error · Error

BigInt cannot be represented in JSON Schema

Error message

BigInt cannot be represented in JSON Schema

What it means

JSON Schema has no representation for arbitrary-precision integers, so `bigintProcessor` (json-schema-processors.ts:102) refuses to convert `z.bigint()`. It throws only when `ctx.unrepresentable === "throw"`, which is the default (to-json-schema.ts:128 sets `params?.unrepresentable ?? "throw"`). Pass `unrepresentable: "any"` to silently emit an empty `any` schema instead.

Source

Thrown at packages/zod/src/v4/core/json-schema-processors.ts:104

      json.maximum = exclusiveMaximum;
      json.exclusiveMaximum = true;
    } else {
      json.exclusiveMaximum = exclusiveMaximum;
    }
  } else if (typeof maximum === "number") {
    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";
  }
};

View on GitHub (pinned to 912f0f51b0)

Solutions

  1. Pass `{ unrepresentable: "any" }` to `z.toJSONSchema()` so bigint nodes become unconstrained schemas.
  2. Replace `z.bigint()` with `z.string()` or `z.number()` in the schema you convert (coerce at the boundary) if you need a concrete JSON type.
  3. If bigint must round-trip, model it as `z.string().regex(/^\d+$/)` and document the convention.

Example fix

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

Strategy: fallback

Validate before calling

// Opt into 'any' for unrepresentable nodes before converting.
const json = z.toJSONSchema(schema, { unrepresentable: "any" });

Type guard

import { z } from "zod";

function containsBigInt(schema: z.ZodType): boolean {
  if (z.core.$ZodType && schema._zod.traits.has("$ZodBigInt")) return true;
  // walk def for nested children recursively as needed
  return false;
}

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: Calling `z.toJSONSchema(schema)` (or `.toJSONSchema()` via the registry / standard-schema path) on a schema tree that contains `z.bigint()` anywhere, with the default `unrepresentable` setting.

Common situations: Generating OpenAPI / JSON Schema docs for an API that uses bigint IDs or timestamps; serializing a shared schema to ship to a frontend; feeding a mixed schema (some bigint columns) into a tool that consumes JSON Schema.

Related errors


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