{"record":{"id":"bf96072a776a8fe6","repo":"colinhacks/zod","slug":"merge-cannot-be-used-on-object-schemas-containi","errorCode":null,"errorMessage":".merge() cannot be used on object schemas containing refinements. Use .safeExtend() instead.","messagePattern":"\\.merge\\(\\) cannot be used on object schemas containing refinements\\. Use \\.safeExtend\\(\\) instead\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/zod/src/v4/core/util.ts","lineNumber":703,"sourceCode":"}\n\nexport function safeExtend(schema: schemas.$ZodObject, shape: schemas.$ZodShape): any {\n  if (!isPlainObject(shape)) {\n    throw new Error(\"Invalid input to safeExtend: expected a plain object\");\n  }\n  const def = mergeDefs(schema._zod.def, {\n    get shape() {\n      const _shape = { ...schema._zod.def.shape, ...shape };\n      assignProp(this, \"shape\", _shape); // self-caching\n      return _shape;\n    },\n  });\n  return clone(schema, def) as any;\n}\n\nexport function merge(a: schemas.$ZodObject, b: schemas.$ZodObject): any {\n  if (a._zod.def.checks?.length) {\n    throw new Error(\".merge() cannot be used on object schemas containing refinements. Use .safeExtend() instead.\");\n  }\n  const def = mergeDefs(a._zod.def, {\n    get shape() {\n      const _shape = { ...a._zod.def.shape, ...b._zod.def.shape };\n      assignProp(this, \"shape\", _shape); // self-caching\n      return _shape;\n    },\n    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,","sourceCodeStart":685,"sourceCodeEnd":721,"githubUrl":"https://github.com/colinhacks/zod/blob/2d90846af918af9602e088812d63a035d47cdbe4/packages/zod/src/v4/core/util.ts#L685-L721","documentation":"Thrown by merge() when the first object argument (`a`) has any refinements in its checks array. `.merge()` rebuilds the schema from `a`'s def and replaces checks with `b`'s checks, which would silently discard `a`'s refinements. The error message redirects to `.safeExtend()`, which preserves both sides' definitions without dropping checks.","triggerScenarios":"Calling `Refined.merge(Other)` where `Refined` was built with `.refine()` or `.check()` on the object node. Only the left-hand schema's checks are guarded; `b`'s checks are carried over into the merged def.","commonSituations":"Combining a base schema that carries invariants with a mixin schema; merging a domain entity with an audit-trail schema; refactoring a flat schema into two halves when one half already has a refinement.","solutions":["Use `a.safeExtend(b._zod.def.shape)` to merge shapes while keeping `a`'s refinements explicit.","Drop the refinement from `a` before merging and re-apply a combined refinement to the result.","Rebuild the merged schema from scratch with `z.object({ ...aFields, ...bFields }).refine(...)`."],"exampleFix":"// before\nconst A = z.object({ x: z.string() }).refine(v => v.x.length > 0);\nconst B = z.object({ y: z.number() });\nconst M = A.merge(B); // throws\n\n// after\nconst M = A.safeExtend(B._zod.def.shape);","handlingStrategy":"validation","validationCode":"function canMerge(a: z.ZodObject): boolean {\n  const checks = (a as any)?._zod?.def?.checks;\n  return !checks || checks.length === 0;\n}\n// if (!canMerge(A)) A.safeExtend(B._zod.def.shape); else A.merge(B);","typeGuard":"function hasObjectRefinements(schema: z.ZodObject): boolean {\n  const checks = (schema as any)?._zod?.def?.checks;\n  return Array.isArray(checks) && checks.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Prefer `.safeExtend(b.shape)` when merging a refined base with another object.","Keep the left operand of `.merge()` refinement-free; attach refinements after merging.","Document which schemas are merge-safe vs invariant-bearing."],"tags":["schema-transformation","merge","refinement","object-schema","zod-v4"],"backgroundTag":null,"analyzedSha":"2d90846af918af9602e088812d63a035d47cdbe4","analyzedAt":"2026-08-11T01:21:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}