{"id":"f7b87486aa94bc94","repo":"colinhacks/zod","slug":"partial-cannot-be-used-on-object-schemas-contai","errorCode":null,"errorMessage":".partial() cannot be used on object schemas containing refinements","messagePattern":"\\.partial\\(\\) cannot be used on object schemas containing refinements","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/zod/src/v4/core/util.ts","lineNumber":729,"sourceCode":"    get catchall() {\n      return b._zod.def.catchall;\n    },\n    checks: b._zod.def.checks ?? [],\n  });\n\n  return clone(a, def) as any;\n}\n\nexport function partial(\n  Class: SchemaClass<schemas.$ZodOptional> | null,\n  schema: schemas.$ZodObject,\n  mask: object | undefined\n): any {\n  const currDef = schema._zod.def;\n  const checks = currDef.checks;\n  const hasChecks = checks && checks.length > 0;\n  if (hasChecks) {\n    throw new Error(\".partial() cannot be used on object schemas containing refinements\");\n  }\n\n  const def = mergeDefs(schema._zod.def, {\n    get shape() {\n      const oldShape = schema._zod.def.shape;\n      const shape: Writeable<schemas.$ZodShape> = { ...oldShape };\n\n      if (mask) {\n        for (const key in mask) {\n          if (!(key in oldShape)) {\n            throw new Error(`Unrecognized key: \"${key}\"`);\n          }\n          if (!(mask as any)[key]) continue;\n          // if (oldShape[key]!._zod.optin === \"optional\") continue;\n          shape[key] = Class\n            ? new Class({\n                type: \"optional\",\n                innerType: oldShape[key]!,","sourceCodeStart":711,"sourceCodeEnd":747,"githubUrl":"https://github.com/colinhacks/zod/blob/912f0f51b0ced654d0069741e7160834dca742ee/packages/zod/src/v4/core/util.ts#L711-L747","documentation":"Thrown by `.partial()` when the target object schema has refinement checks (guard at util.ts:726-728). Making fields optional would change the input shape that refinements validate against, risking silent invalidation, so `.partial()` refuses. There is no `safePartial` variant — you must restructure.","triggerScenarios":"Calling `Schema.partial()` or `Schema.partial({ field: true })` on a schema that has `.refine()/.superRefine()` attached.","commonSituations":"Building an update/patch schema from a validated create schema via `.partial()`; sharing a single source-of-truth object with refinements across POST/PATCH handlers.","solutions":["Move refinements off the base object, call `.partial()` on the bare object, then reattach refinements to the result.","Define the create schema without cross-field checks, derive `.partial()` for updates, and add refinements per variant.","Use a separate update schema entirely instead of deriving with `.partial()`."],"exampleFix":"// before\nconst User = z.object({ id: z.string(), email: z.string() }).refine(d => d.id !== d.email);\nconst Update = User.partial(); // throws\n\n// after\nconst Base = z.object({ id: z.string(), email: z.string() });\nconst Update = Base.partial().refine(d => d.id !== d.email);","handlingStrategy":"type-guard","validationCode":"function hasRefinements(s: z.core.$ZodObject): boolean {\n  return !!s._zod.def.checks?.length;\n}\nif (hasRefinements(User)) {\n  // restructure: bare object -> partial -> reattach refine\n}","typeGuard":"function isRefinementFree(s: z.core.$ZodObject): boolean {\n  return !s._zod.def.checks?.length;\n}","tryCatchPattern":null,"preventionTips":["Define base objects without refinements; `.partial()` the bare object; re-add refinements after.","Maintain separate create/update schemas instead of deriving update from a validated create schema."],"tags":["zod","object-schema","partial","refinement"],"analyzedSha":"912f0f51b0ced654d0069741e7160834dca742ee","analyzedAt":"2026-08-03T17:41:55.908Z","schemaVersion":2}