colinhacks/zod · error · Error
.omit() cannot be used on object schemas containing refineme
Error message
.omit() cannot be used on object schemas containing refinements
What it means
Thrown by `.omit()` when the target object schema has refinement checks attached (`.refine()`, `.superRefine()`, or similar) — see the `hasChecks` guard at util.ts:633-635. Refinements operate over the whole object, so dropping fields via `.omit()` would silently invalidate them; the library refuses rather than guess. The message points the user toward restructuring instead.
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 912f0f51b0)
Solutions
- Move the refinement onto a separate schema after `.omit()`: define the bare object, `omit` it, then attach `.refine()` to the result.
- Replace the refinement with per-field checks (`.refine()` on individual fields) so it survives `.omit()`.
- Use `.safeExtend()` or rebuild the shape manually instead of `.omit()` when you must preserve the refinement.
Example fix
// before
const User = z.object({ id: z.string(), email: z.string() }).refine(d => d.id !== d.email);
const NewUser = User.omit({ id: true }); // throws
// after
const Base = z.object({ id: z.string(), email: z.string() });
const NewUser = Base.omit({ id: true }).refine(d => d.id !== d.email); Defensive patterns
Strategy: type-guard
Validate before calling
function hasRefinements(s: z.core.$ZodObject): boolean {
return !!s._zod.def.checks?.length;
}
if (hasRefinements(User)) {
// omit on a bare variant instead
} Type guard
function isRefinementFree(s: z.core.$ZodObject): s is z.core.$ZodObject & { _zod: { def: { checks: [] } } } {
return !s._zod.def.checks?.length;
} Try / catch
try { const Out = User.omit({ id: true }); } catch (e) {
if (e instanceof Error && /omit.*refinements/.test(e.message)) {
const Out = Bare.omit({ id: true }).refine(/* original */);
} else throw e;
} Prevention
- Define base objects without refinements and attach `.refine()` only on the final composed schema.
- Prefer per-field refinements over object-level ones when you'll need `.omit()`.
When it happens
Trigger: Calling `Schema.omit({...})` on a schema built as `z.object({...}).refine(...)` or `z.object({...}).superRefine(...)`, or composing with any check that lands in `def.checks`.
Common situations: Building a create/update variant of a validated schema by omitting fields (e.g. `User.omit({ id: true })`) when `User` was defined with cross-field validation; refactoring validation into the base object; migrating from v3 patterns that allowed this.
Related errors
- Cannot overwrite keys on object schemas containing refinemen
- .merge() cannot be used on object schemas containing refinem
- .partial() cannot be used on object schemas containing refin
- Unrecognized key: "${key}"
- Invalid input to extend: expected a plain object
AI-assisted analysis of colinhacks/zod@912f0f51b0 (2026-08-03).
Data as JSON: /data/errors/e5bee1fc45abd1f0.json.
Report an issue: GitHub.