{"record":{"id":"5c01fb2600917b9b","repo":"colinhacks/zod","slug":"invalid-input-to-extend-expected-a-plain-object","errorCode":null,"errorMessage":"Invalid input to extend: expected a plain object","messagePattern":"Invalid input to extend: expected a plain object","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/zod/src/v4/core/util.ts","lineNumber":661,"sourceCode":"        if (!(key in currDef.shape)) {\n          throw new Error(`Unrecognized key: \"${key}\"`);\n        }\n        if (!(mask as any)[key]) continue;\n\n        delete newShape[key];\n      }\n      assignProp(this, \"shape\", newShape); // self-caching\n      return newShape;\n    },\n    checks: [],\n  });\n\n  return clone(schema, def);\n}\n\nexport function extend(schema: schemas.$ZodObject, shape: schemas.$ZodShape): any {\n  if (!isPlainObject(shape)) {\n    throw new Error(\"Invalid input to extend: expected a plain object\");\n  }\n\n  const checks = schema._zod.def.checks;\n  const hasChecks = checks && checks.length > 0;\n  if (hasChecks) {\n    // Only throw if new shape overlaps with existing shape\n    // Use getOwnPropertyDescriptor to check key existence without accessing values\n    const existingShape = schema._zod.def.shape;\n    for (const key in shape) {\n      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 };","sourceCodeStart":643,"sourceCodeEnd":679,"githubUrl":"https://github.com/colinhacks/zod/blob/2d90846af918af9602e088812d63a035d47cdbe4/packages/zod/src/v4/core/util.ts#L643-L679","documentation":"Thrown by extend() when the shape argument fails isPlainObject(). Zod requires the shape to be a plain object literal (prototype of Object.prototype or no modified constructor/prototype) so it can safely spread keys as field schemas. Class instances, arrays, Maps, null, and primitives are rejected before any keys are read.","triggerScenarios":"Calling `schema.extend(SomeClassInstance)`, `schema.extend([...])`, `schema.extend(null)`, or passing a schema object, a Record subclass, or a Proxy whose constructor/prototype has been swapped. Also triggered by passing a `z.object(...)` result instead of its inner shape.","commonSituations":"Passing a class instance (e.g. a typed Record from a serializer) instead of a literal; accidentally feeding an array of [key, schema] pairs; handing in a schema instead of a shape map; using a custom object wrapper that mutates the prototype.","solutions":["Pass a plain object literal: `{ newField: z.string() }`.","If your shape lives in a class/Map/wrapper, spread it into a fresh `{}` first: `schema.extend({ ...mapOrInstance })` after extracting the schema entries.","Ensure the value is not an array, null, or a primitive — extend takes a key→schema map only."],"exampleFix":"// before\nconst extra = new Map([['id', z.string()]]);\nBase.extend(extra); // throws\n\n// after\nconst extra = { id: z.string() };\nBase.extend(extra);","handlingStrategy":"type-guard","validationCode":"function asShape(shape: unknown): Record<string, z.ZodType> {\n  if (!isPlainShape(shape)) {\n    throw new TypeError('extend() expects a plain object of key -> ZodType');\n  }\n  return shape as Record<string, z.ZodType>;\n}\n// base.extend(asShape(maybeShape));","typeGuard":"function isPlainShape(o: unknown): o is Record<string, z.ZodType> {\n  if (o === null || typeof o !== 'object' || Array.isArray(o)) return false;\n  const proto = Object.getPrototypeOf(o);\n  return proto === null || proto === Object.prototype;\n}","tryCatchPattern":null,"preventionTips":["Always pass a freshly-constructed object literal to `.extend()`.","Coerce Maps/arrays with `Object.fromEntries(...)` before extending.","Never pass a schema instance or a class instance where a shape map is expected."],"tags":["schema-transformation","extend","type-validation","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"}