colinhacks/zod · error · Error
not is not supported in Zod (except { not: {} } for never)
Error message
not is not supported in Zod (except { not: {} } for never) What it means
Thrown by convertBaseSchema when a JSON Schema uses the `not` keyword in any form other than `{ not: {} }`, which the converter maps to z.never(). General negation constraints are not representable in Zod's additive model.
Source
Thrown at packages/zod/src/v4/classic/from-json-schema.ts:153
if (path[0] === defsKey) {
const key = path[1];
if (!key || !ctx.defs[key]) {
throw new Error(`Reference not found: ${ref}`);
}
return ctx.defs[key]!;
}
throw new Error(`Reference not found: ${ref}`);
}
function convertBaseSchema(schema: JSONSchema.JSONSchema, ctx: ConversionContext): ZodType {
// Handle unsupported features
if (schema.not !== undefined) {
// Special case: { not: {} } represents never
if (typeof schema.not === "object" && Object.keys(schema.not).length === 0) {
return z.never();
}
throw new Error("not is not supported in Zod (except { not: {} } for never)");
}
if (schema.unevaluatedItems !== undefined) {
throw new Error("unevaluatedItems is not supported");
}
if (schema.unevaluatedProperties !== undefined) {
throw new Error("unevaluatedProperties is not supported");
}
if (schema.if !== undefined || schema.then !== undefined || schema.else !== undefined) {
throw new Error("Conditional schemas (if/then/else) are not supported");
}
if (schema.dependentSchemas !== undefined || schema.dependentRequired !== undefined) {
throw new Error("dependentSchemas and dependentRequired are not supported");
}
// Handle $ref
if (schema.$ref) {
const refPath = schema.$ref;
if (ctx.refs.has(refPath)) {View on GitHub (pinned to 912f0f51b0)
Solutions
- If you intend 'reject everything' use `{ not: {} }`, which converts to z.never().
- Replace `not` with an affirmative constraint expressible in Zod: e.g. use `anyOf`/`oneOf` to enumerate allowed shapes, or move the negation into a `.refine()` after conversion.
- Strip `not` from the source schema and apply the equivalent check downstream in code.
Example fix
// before
{ "not": { "type": "string" } } // 'not a string'
// after
// enumerate allowed types instead, then refine
const s = z.any().refine((v) => typeof v !== "string", "must not be a string"); Defensive patterns
Strategy: validation
Validate before calling
function assertNoNot(schema: any) {
if (schema.not !== undefined && !(typeof schema.not === "object" && Object.keys(schema.not).length === 0)) {
throw new Error("`not` is unsupported; only { not: {} } is allowed");
}
} Type guard
function isSupportedNot(schema: any): boolean {
return schema.not === undefined || (typeof schema.not === "object" && Object.keys(schema.not).length === 0);
} Prevention
- Author affirmative schemas (allow-lists) instead of negations.
- Move 'not' logic into a post-conversion refine.
- Reject schemas with `not` at intake if conversion is required.
When it happens
Trigger: A schema like `{ not: { type: "string" } }` (anything except a string), `{ not: { enum: [...] } }`, or `{ not: { const: 0 } }`. Even `{ not: { type: "object" } }` is rejected.
Common situations: Inheriting schemas authored for Ajv or other validators that fully support `not`; OpenAPI extensions that use `not` to forbid shapes; trying to express 'not one of' constraints.
Related errors
- unevaluatedItems is not supported
- unevaluatedProperties is not supported
- Conditional schemas (if/then/else) are not supported
- dependentSchemas and dependentRequired are not supported
- Unsupported type: ${type}
AI-assisted analysis of colinhacks/zod@912f0f51b0 (2026-08-03).
Data as JSON: /data/errors/c7b7d730ba51a2d3.json.
Report an issue: GitHub.