colinhacks/zod · error · Error

Undefined cannot be represented in JSON Schema

Error message

Undefined cannot be represented in JSON Schema

What it means

Thrown by toJSONSchema() when a ZodUndefined schema (z.undefined()) is encountered with unrepresentable set to 'throw' (default). JSON has no representation for the explicit absence that undefined denotes (null is a value; undefined is not), so the converter refuses rather than silently emitting a wrong type.

Solutions

  1. Pass { unrepresentable: 'any' } to toJSONSchema() so the undefined field collapses to {}.
  2. Model absence with z.optional(...) / omitting the key instead of an explicit z.undefined() field for the exported contract.
  3. Use z.null() where the external representation should be JSON null.

Example fix

// before (throws)
const Schema = z.object({ ghost: z.undefined() });
z.toJSONSchema(Schema);

// after
const Schema = z.object({ ghost: z.undefined() });
z.toJSONSchema(Schema, { unrepresentable: 'any' });
Defensive patterns

Strategy: try-catch

Validate before calling

const opts = schemaContains(schema, (s) => s._zod.def.type === 'undefined')
  ? { unrepresentable: 'any' }
  : {};
const json = z.toJSONSchema(schema, opts);

Type guard

function hasUndefined(schema) {
  return schema._zod.def.type === 'undefined';
}

Try / catch

try {
  return z.toJSONSchema(schema);
} catch (e) {
  if (e.message === 'Undefined cannot be represented in JSON Schema') {
    return z.toJSONSchema(schema, { unrepresentable: 'any' });
  }
  throw e;
}

Prevention

When it happens

Trigger: A schema with an explicitly-typed z.undefined() field passed to toJSONSchema(). Using z.undefined() to model 'property must be absent' and then exporting the schema to JSON Schema.

Common situations: Differentiating 'missing key' (undefined) from 'null value' in input, then needing to document that contract in JSON Schema/OpenAPI.

Related errors


AI-assisted analysis of colinhacks/zod@2d90846af9 (2026-08-11). Data as JSON: /api/errors/daeb7c79fde9cf18. Report an issue: GitHub.

Appendix: source

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

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");
  }
};

export const voidProcessor: Processor<schemas.$ZodVoid> = (_schema, ctx, _json, _params) => {
  if (ctx.unrepresentable === "throw") {
    throw new Error("Void cannot be represented in JSON Schema");
  }
};

export const neverProcessor: Processor<schemas.$ZodNever> = (_schema, _ctx, json, _params) => {
  json.not = {};
};

export const anyProcessor: Processor<schemas.$ZodAny> = (_schema, _ctx, _json, _params) => {
  // empty schema accepts anything
};

export const unknownProcessor: Processor<schemas.$ZodUnknown> = (_schema, _ctx, _json, _params) => {

View on GitHub (pinned to 2d90846af9)