colinhacks/zod · error · Error

.partial() cannot be used on object schemas containing…

Error message

.partial() cannot be used on object schemas containing refinements

What it means

Thrown by partial() when the source object has refinements. `.partial()` wraps selected (or all) fields in an optional wrapper and rebuilds the schema with an empty checks array, which would silently discard object-level refinements. Like `.pick()`/`.omit()`, the operation is blocked rather than losing the invariants.

Solutions

  1. Apply `.partial()` to a refinement-free base, then re-apply the refinement to the result.
  2. Build the partial schema from scratch with `z.object({ a: z.string().optional() })` and add only the refinements that still make sense.
  3. Move the refinement to leaf fields so it survives the partial() rebuild.

Example fix

// before
const S = z.object({ a: z.string(), b: z.string() }).refine(v => v.a !== v.b);
const P = S.partial(); // throws

// after
const P = z.object({ a: z.string().optional(), b: z.string().optional() })
  .refine(v => (v.a ?? '') !== (v.b ?? ''));
Defensive patterns

Strategy: validation

Validate before calling

function canPartial(schema: z.ZodObject): boolean {
  const checks = (schema as any)?._zod?.def?.checks;
  return !checks || checks.length === 0;
}
// if (!canPartial(S)) { /* rebuild from a refinement-free base */ }

Type guard

function hasObjectRefinements(schema: z.ZodObject): boolean {
  const checks = (schema as any)?._zod?.def?.checks;
  return Array.isArray(checks) && checks.length > 0;
}

Prevention

When it happens

Trigger: Calling `myObject.partial()` or `myObject.partial({ a: true })` on an object schema that has `.refine()`/`.check()` attached at the object node. Eager throw at `.partial()` call time.

Common situations: Building a PATCH/update schema from a full entity that carries cross-field invariants; making a form-input schema optional where the source has validation rules; layering `.partial()` over a schema that gained a refinement after a refactor.

Related errors


AI-assisted analysis of colinhacks/zod@2d90846af9 (2026-08-11). Data as JSON: /api/errors/f7b87486aa94bc94. Report an issue: GitHub.

Appendix: source

Thrown at packages/zod/src/v4/core/util.ts:729

    get catchall() {
      return b._zod.def.catchall;
    },
    checks: b._zod.def.checks ?? [],
  });

  return clone(a, def) as any;
}

export function partial(
  Class: SchemaClass<schemas.$ZodOptional> | null,
  schema: schemas.$ZodObject,
  mask: object | undefined
): any {
  const currDef = schema._zod.def;
  const checks = currDef.checks;
  const hasChecks = checks && checks.length > 0;
  if (hasChecks) {
    throw new Error(".partial() cannot be used on object schemas containing refinements");
  }

  const def = mergeDefs(schema._zod.def, {
    get shape() {
      const oldShape = schema._zod.def.shape;
      const shape: Writeable<schemas.$ZodShape> = { ...oldShape };

      if (mask) {
        for (const key in mask) {
          if (!(key in oldShape)) {
            throw new Error(`Unrecognized key: "${key}"`);
          }
          if (!(mask as any)[key]) continue;
          // if (oldShape[key]!._zod.optin === "optional") continue;
          shape[key] = Class
            ? new Class({
                type: "optional",
                innerType: oldShape[key]!,

View on GitHub (pinned to 2d90846af9)