colinhacks/zod · error · Error
.omit() cannot be used on object schemas containing…
Error message
.omit() cannot be used on object schemas containing refinements
What it means
Thrown by the omit() helper. Identical contract to `.pick()`: `.omit()` rebuilds the schema with an empty checks array, so dropping object-level refinements silently is forbidden. The guard fires whenever `def.checks.length > 0` on the source object.
Solutions
- Re-apply the refinement to the omitted result so it is not silently lost.
- Factor out a refinement-free base schema and call `.omit()` on that, layering refinements on each variant.
- Build the public schema from scratch with only the needed fields.
Example fix
// before
const User = z.object({ email: z.string(), pwd: z.string() })
.refine(v => v.email.length > 0);
const Public = User.omit({ pwd: true }); // throws
// after
const Public = z.object({ email: z.string() })
.refine(v => v.email.length > 0); Defensive patterns
Strategy: validation
Validate before calling
function canOmit(schema: z.ZodObject): boolean {
const checks = (schema as any)._zod?.def?.checks;
return !checks || checks.length === 0;
}
// if (!canOmit(MyObject)) { /* drop refinement or rebuild */ } Type guard
function hasObjectRefinements(schema: z.ZodObject): boolean {
const checks = (schema as any)._zod?.def?.checks;
return Array.isArray(checks) && checks.length > 0;
} Prevention
- Keep a refinement-free base for DTO/subset construction.
- Re-apply refinements explicitly after `.omit()` on a clean base.
- Avoid attaching cross-field refinements to schemas you intend to slice.
When it happens
Trigger: Calling `myObject.omit({ secret: true })` where `myObject` has a `.refine()`, `.check()`, or any object-level refinement attached. Eager throw at the `.omit()` call site.
Common situations: Stripping sensitive fields (passwordHash, internal flags) from a schema that also enforces a cross-field invariant; reusing a domain entity schema for a public response shape; adding a refinement upstream and forgetting an existing `.omit()` depends on it.
Related errors
- Cannot overwrite keys on object schemas containing…
- .merge() cannot be used on object schemas containing…
- .partial() cannot be used on object schemas containing…
- .pick() cannot be used on object schemas containing…
- Invalid input to extend: expected a plain object
AI-assisted analysis of colinhacks/zod@2d90846af9 (2026-08-11).
Data as JSON: /api/errors/e5bee1fc45abd1f0.
Report an issue: GitHub.
Appendix: source
Thrown at packages/zod/src/v4/core/util.ts:636
newShape[key] = currDef.shape[key]!;
}
assignProp(this, "shape", newShape); // self-caching
return newShape;
},
checks: [],
});
return clone(schema, def) as any;
}
export function omit(schema: schemas.$ZodObject, mask: object): any {
const currDef = schema._zod.def;
const checks = currDef.checks;
const hasChecks = checks && checks.length > 0;
if (hasChecks) {
throw new Error(".omit() cannot be used on object schemas containing refinements");
}
const def = mergeDefs(schema._zod.def, {
get shape() {
const newShape: Writeable<schemas.$ZodShape> = { ...schema._zod.def.shape };
for (const key in mask) {
if (!(key in currDef.shape)) {
throw new Error(`Unrecognized key: "${key}"`);
}
if (!(mask as any)[key]) continue;
delete newShape[key];
}
assignProp(this, "shape", newShape); // self-caching
return newShape;
},
checks: [],
});View on GitHub (pinned to 2d90846af9)