{"id":"a4eead5478eb1497","repo":"colinhacks/zod","slug":"invalid-input-to-safeextend-expected-a-plain-obje","errorCode":null,"errorMessage":"Invalid input to safeExtend: expected a plain object","messagePattern":"Invalid input to safeExtend: expected a plain object","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/zod/src/v4/core/util.ts","lineNumber":689,"sourceCode":"      if (Object.getOwnPropertyDescriptor(existingShape, key) !== undefined) {\n        throw new Error(\"Cannot overwrite keys on object schemas containing refinements. Use `.safeExtend()` instead.\");\n      }\n    }\n  }\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 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 };","sourceCodeStart":671,"sourceCodeEnd":707,"githubUrl":"https://github.com/colinhacks/zod/blob/912f0f51b0ced654d0069741e7160834dca742ee/packages/zod/src/v4/core/util.ts#L671-L707","documentation":"Thrown by `.safeExtend()` when the argument is not a plain object (guard at util.ts:688, same `isPlainObject` check as `.extend()`). `.safeExtend()` is the refinement-tolerant variant of `.extend()`, but it still requires a literal shape map of `ZodType` values.","triggerScenarios":"Calling `schema.safeExtend(null)`, `schema.safeExtend(array)`, or passing a non-plain-object value where a shape record is expected.","commonSituations":"Migrating a `.extend()` call to `.safeExtend()` to bypass refinement guards but keeping a malformed argument; passing a single schema instance instead of `{ key: schema }`; deserializing shapes from config without reconstruction.","solutions":["Pass a plain object literal of field schemas: `schema.safeExtend({ field: z.string() })`.","If building dynamically, use `Object.fromEntries()` to materialize a plain object first.","Add a TypeScript annotation `const shape: z.core.$ZodShape = {...}` to surface shape errors at compile time."],"exampleFix":"// before\nconst Extended = User.safeExtend(SomeSchema);\n\n// after\nconst Extended = User.safeExtend({ field: SomeSchema });","handlingStrategy":"type-guard","validationCode":"function isPlainShape(v: unknown): v is Record<string, z.core.$ZodType> {\n  return typeof v === 'object' && v !== null &&\n    [Object.prototype, null].includes(Object.getPrototypeOf(v));\n}\nif (!isPlainShape(arg)) throw new Error('safeExtend needs a plain object');\nconst Out = schema.safeExtend(arg);","typeGuard":"function isZodShape(v: unknown): v is z.core.$ZodShape {\n  return typeof v === 'object' && v !== null &&\n    [Object.prototype, null].includes(Object.getPrototypeOf(v)) &&\n    Object.values(v).every(x => x && typeof x === 'object' && '_zod' in x);\n}","tryCatchPattern":null,"preventionTips":["Pass `{ field: schema }` literals only.","Annotate dynamic shapes with `z.core.$ZodShape` to surface type errors."],"tags":["zod","object-schema","safeextend","type-error"],"analyzedSha":"912f0f51b0ced654d0069741e7160834dca742ee","analyzedAt":"2026-08-03T17:41:55.908Z","schemaVersion":2}