colinhacks/zod · error · Error
Date cannot be represented in JSON Schema
Error message
Date cannot be represented in JSON Schema
What it means
Thrown by toJSONSchema() when a ZodDate schema (z.date()) is encountered with unrepresentable 'throw' (default). ZodDate validates a JS Date object instance; JSON Schema has no date-instance type (only string formats like 'date-time'), so emitting one would change the validation semantics and the converter refuses.
Solutions
- For the exported/JSON contract, use z.iso.datetime() or z.string().datetime() (which produce { type: 'string', format: 'date-time' }) instead of z.date().
- Pass { unrepresentable: 'any' } to toJSONSchema() to emit {} for date fields if you accept the loss of validation metadata.
- Maintain two schemas: a runtime schema with z.date() and an export schema with z.iso.datetime(), sharing field shape via composition.
Example fix
// before (throws)
const Schema = z.object({ createdAt: z.date() });
z.toJSONSchema(Schema);
// after (string date-time for the JSON contract)
const Schema = z.object({ createdAt: z.iso.datetime() });
z.toJSONSchema(Schema);
// { type: 'object', properties: { createdAt: { type: 'string', format: 'date-time' } } } Defensive patterns
Strategy: try-catch
Validate before calling
// Prefer exporting the wire (string) shape rather than the Date-instance shape.
function exportSchema(runtimeSchema) {
// Replace z.date() with z.iso.datetime() for export, or accept the any fallback.
try {
return z.toJSONSchema(runtimeSchema);
} catch (e) {
if (e.message === 'Date cannot be represented in JSON Schema') {
return z.toJSONSchema(runtimeSchema, { unrepresentable: 'any' });
}
throw e;
}
} Type guard
function hasDate(schema) {
return schema._zod.def.type === 'date';
} Try / catch
try {
return z.toJSONSchema(schema);
} catch (e) {
if (e.message === 'Date cannot be represented in JSON Schema') {
// Either downgrade to string date-time or allow the any fallback
return z.toJSONSchema(schema, { unrepresentable: 'any' });
}
throw e;
} Prevention
- Model external/API contracts with z.iso.datetime() / z.string().datetime() and reserve z.date() for runtime parsing.
- When you must export a Date-instance schema, pass { unrepresentable: 'any' } explicitly.
- Document each model as 'runtime' or 'export' to avoid mixing the two.
When it happens
Trigger: Calling toJSONSchema() on a schema containing z.date(). Generating OpenAPI from a model whose timestamps are Date instances rather than ISO strings.
Common situations: Server models that parse into Date objects for runtime use, but whose wire/API contract is an ISO 8601 string — exporting the runtime schema directly mismatches the wire format.
Related errors
- BigInt cannot be represented in JSON Schema
- BigInt literals cannot be represented in JSON Schema
- Custom types cannot be represented in JSON Schema
- Dynamic catch values are not supported in JSON Schema
- Function types cannot be represented in JSON Schema
AI-assisted analysis of colinhacks/zod@2d90846af9 (2026-08-11).
Data as JSON: /api/errors/168b5634da54477b.
Report an issue: GitHub.
Appendix: source
Thrown at packages/zod/src/v4/core/json-schema-processors.ts:150
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) => {
// empty schema accepts anything
};
export const dateProcessor: Processor<schemas.$ZodDate> = (_schema, ctx, _json, _params) => {
if (ctx.unrepresentable === "throw") {
throw new Error("Date cannot be represented in JSON Schema");
}
};
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") {View on GitHub (pinned to 2d90846af9)