colinhacks/zod · error · Error
Custom types cannot be represented in JSON Schema
Error message
Custom types cannot be represented in JSON Schema
What it means
Thrown by toJSONSchema() when a ZodCustom schema (z.custom(...)) is encountered with unrepresentable 'throw' (default). A custom check carries arbitrary validation logic with no declarative JSON Schema equivalent, so the converter cannot faithfully emit a constraint.
Solutions
- Pass { unrepresentable: 'any' } to toJSONSchema() so the custom field becomes {}.
- Express what you can declaratively (z.string().email(), patterns, min/max) and keep only truly-unrepresentable logic in z.custom — accepting that JSON Schema loses it.
- Use the override() hook of toJSONSchema() to inject a custom JSON Schema fragment for the field, decoupling runtime validation from the exported contract.
Example fix
// before (throws)
const Even = z.custom((x) => typeof x === 'number' && x % 2 === 0);
z.toJSONSchema(Even);
// after
const Even = z.custom((x) => typeof x === 'number' && x % 2 === 0);
z.toJSONSchema(Even, { unrepresentable: 'any' }); // {}
// or declare the representable part and refine separately
const Even = z.number().refine((x) => x % 2 === 0); Defensive patterns
Strategy: try-catch
Validate before calling
const opts = schemaContains(schema, (s) => s._zod.def.type === 'custom')
? { unrepresentable: 'any' }
: {};
const json = z.toJSONSchema(schema, opts); Type guard
function hasCustom(schema) {
return schema._zod.def.type === 'custom';
} Try / catch
try {
return z.toJSONSchema(schema);
} catch (e) {
if (e.message === 'Custom types cannot be represented in JSON Schema') {
return z.toJSONSchema(schema, { unrepresentable: 'any' });
}
throw e;
} Prevention
- Prefer declarative built-in constraints over z.custom() wherever possible — they survive JSON Schema export.
- Isolate z.custom()/refine() logic in runtime-only schemas; export a plain data schema.
- Use the override() hook to inject a hand-written JSON Schema fragment for fields that need custom validation.
When it happens
Trigger: Calling toJSONSchema() on a schema containing z.custom(() => check(...)). Composing a custom validator into a model and then exporting the model to JSON Schema/OpenAPI.
Common situations: Refining schemas with business rules (z.custom / .refine) and expecting the JSON Schema output to encode those rules.
Related errors
- BigInt cannot be represented in JSON Schema
- BigInt literals cannot be represented in JSON Schema
- Date 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/f7f46596d5985a28.
Report an issue: GitHub.
Appendix: source
Thrown at packages/zod/src/v4/core/json-schema-processors.ts:246
if (mime.length === 1) {
file.contentMediaType = mime[0]!;
Object.assign(_json, file);
} else {
Object.assign(_json, file); // shared props at root
_json.anyOf = mime.map((m) => ({ contentMediaType: m })); // only contentMediaType differs
}
} else {
Object.assign(_json, file);
}
};
export const successProcessor: Processor<schemas.$ZodSuccess> = (_schema, _ctx, json, _params) => {
(json as JSONSchema.BooleanSchema).type = "boolean";
};
export const customProcessor: Processor<schemas.$ZodCustom> = (_schema, ctx, _json, _params) => {
if (ctx.unrepresentable === "throw") {
throw new Error("Custom types cannot be represented in JSON Schema");
}
};
export const functionProcessor: Processor<schemas.$ZodFunction> = (_schema, ctx, _json, _params) => {
if (ctx.unrepresentable === "throw") {
throw new Error("Function types cannot be represented in JSON Schema");
}
};
export const transformProcessor: Processor<schemas.$ZodTransform> = (_schema, ctx, _json, _params) => {
if (ctx.unrepresentable === "throw") {
throw new Error("Transforms cannot be represented in JSON Schema");
}
};
export const mapProcessor: Processor<schemas.$ZodMap> = (_schema, ctx, _json, _params) => {
if (ctx.unrepresentable === "throw") {
throw new Error("Map cannot be represented in JSON Schema");View on GitHub (pinned to 2d90846af9)