Repository: colinhacks/zod
Pull request #4380 (2025-05-16 03:49:02)

Fix typo in json-schema.mdx


Patch:
diff --git a/packages/docs/content/api.mdx b/packages/docs/content/api.mdx
index 0cc55f50..866a5f65 100644
--- a/packages/docs/content/api.mdx
+++ b/packages/docs/content/api.mdx
@@ -1119,6 +1119,10 @@ type Category = z.infer<typeof Category>;
 // { name: string; subcategories: Category[] }
 ```
 
+<Callout type="warn"> 
+  Though recursive schemas are supported, passing cyclical data into Zod will cause an infinite loop.
+</Callout>
+
 You can also represent *mutually recursive types*:
 
 ```ts
@@ -1137,11 +1141,105 @@ const Post = z.object({
 });
 ```
 
-All object APIs (pick, omit, required, partial, etc) work as you'd expect.
+All object APIs (`.pick()`, `.omit()`, `.required()`, `.partial()`, etc.) work as you'd expect.
 
-<Callout type="warn"> 
-  Though recursive schemas are supported, passing cyclical data into Zod will cause an infinite loop.
-</Callout>
+Due to TypeScript limitations, recursive type inference can be finicky, and it only works in certain scenarios. Some more complicated types may trigger recursive type errors like this:
+
+```ts
+const Activity = z.object({
+  name: z.string(),
+  get subactivities() {
+    // ^ ❌ 'subactivities' implicitly has return type 'any' because it does not 
+    // // have a return type annotation and is referenced directly or indirectly 
+    // in one of its return expressions.ts(7023)
+
+    return z.union([z.null(), Activity]);
+  },
+});
+```
+
+In these cases, you can resolve the error with a type annotation on the offending getter:
+
+```ts
+const Activity = z.object({
+  name: z.string(),
+  get subactivities(): z.ZodUnion<[z.ZodNull, typeof Activity]> { // ✅
+    return z.union([z.null(), Activity]); 
+  },
+});
+```
+{/* 
+<Accordions>
+  <Accordion title="Resolving type errors in recursive schemas">
+    Recursive type inference can by mysterious. TypeScript is capable of it in certain limited scenarios. Depending on what you're trying to do, you may encounter errors like this:
+
+    ```ts
+    export const Activity = z.object({
+      name: z.string(),
+      get children() {
+        // ^ ❌ 'children' implicitly has return type 'any' because it does not 
+        // have a return type annotation and is referenced directly or indirectly 
+        // in one of its return expressions.ts(7023)
+
+        return z.optional(z.array(Activity)); //.optional();
+      },
+    });
+    ```
+
+    Here are a couple rules of thumb:
+
+    ### Object types only 
+    
+    Generally speaking, recursive inference only works with object types that are referencing each other. TypeScript has special handling for resolving getter-based recursive objects, which is what Zod relies on. If you try to add non-object types into the mix, you'll likely encounter errors.
+
+    ```ts
+    const Activity = z.object({
+      name: z.string(),
+      get children() { // ❌ type error
+        return z.optional(ActivityArray);
+      },
+    });
+
+    const ActivityArray = z.array(Activity);
+    ```
+
+    Sometimes you can get around this limitation by defining 
+
+
+    ### Avoid nesting function calls
+    
+    Functions like `z.array()` and `z.optional()` accept Zod schemas, so when you use them TypeScript will do some type-checking on their inputs to make sure they are valid. But type checking is the enemy of recursive type inference—it's hard for TypeScript to *check* and *infer* types at the same time. Methods do not have this problem, so prefer methods over functions when possible (sorry Zod Mini users).
+
+    ```ts
+    const Activity = z.object({
+      name: z.string(),
+      get subactivities() {
+        // ^ ❌ 'subactivities' implicitly has return type 'any' because it does not 
+        // // have a return type annotation and is referenced directly or indirectly 
+        // in one of its return expressions.ts(7023)
+
+        return z.union([z.null(), Activity]);
+      },
+    });
+    ```
+
+    ### Fall back to type annotations on your getters
+    
+    When in doubt, you can generally sidestep these issues with some carefully deployed type annotations on your getters. Due to the limitations described above, this is particularly necessary when using Zod Mini.
+
+    ```ts
+    import { z } from "zod/v4";
+
+    const Activity = z.object({
+      name: z.string(),
+      get subactivities(): z.ZodMiniDefault<z.ZodMiniArray<typeof Activity>> {
+        return z._default(z.array(Activity), []);
+      },
+    });
+    ```
+
+  </Accordion>
+</Accordions> */}
 
 ## Arrays
 
diff --git a/packages/docs/content/json-schema.mdx b/packages/docs/content/json-schema.mdx
index 88674355..94298d72 100644
--- a/packages/docs/content/json-schema.mdx
+++ b/packages/docs/content/json-schema.mdx
@@ -29,7 +29,7 @@ z.toJSONSchema(schema)
 // }
 ```
 
-All schema & checks are converted to their closest JSON Schema equivalent. Some types have no analog and cannot be reasonably represented. See the [`unrepresentable'](#unrepresentable) section below for more information on handling these cases.
+All schema & checks are converted to their closest JSON Schema equivalent. Some types have no analog and cannot be reasonably represented. See the [`unrepresentable`](#unrepresentable) section below for more information on handling these cases.
 
 ```ts
 z.bigint(); // ❌
diff --git a/packages/docs/content/v4/changelog.mdx b/packages/docs/content/v4/changelog.mdx
index 73bae402..d2723b53 100644
--- a/packages/docs/content/v4/changelog.mdx
+++ b/packages/docs/content/v4/changelog.mdx
@@ -253,6 +253,7 @@ In Zod 3, `z.number().safe()` is deprecated. It now behaves identically to `.int
 ### `.int()` accepts safe integers only
 
 The `z.number().int()` API no longer accepts unsafe integers (outside the range of `Number.MIN_SAFE_INTEGER` and `Number.MAX_SAFE_INTEGER`). Using integers out of this range causes spontaneous rounding errors. (Also: You should switch to `z.int()`.)
+
 ## `z.string()` updates
 
 ### deprecates `.email()` etc
@@ -287,6 +288,11 @@ z.string().email(); // ❌ deprecated
 z.email(); // ✅ 
 ```
 
+
+### no padding in `.base64url()` 
+
+Padding is no longer allowed in `z.base64url()` (formerly `z.string().base64url()`). Generally it's desirable for base64url strings to be unpadded and URL-safe. 
+
 ### drops `z.string().ip()` 
 
 This has been replaced with separate `.ipv4()` and `.ipv6()` methods. Use `z.union()` to combine them if you need to accept both.
diff --git a/packages/zod/src/v4/classic/errors.ts b/packages/zod/src/v4/classic/errors.ts
index b3dd78b5..04e909c2 100644
--- a/packages/zod/src/v4/classic/errors.ts
+++ b/packages/zod/src/v4/classic/errors.ts
@@ -1,5 +1,5 @@
 import * as core from "zod/v4/core";
-import { type $ZodError, _$ZodError } from "zod/v4/core";
+import { $ZodError } from "zod/v4/core";
 
 /** @deprecated Use `z.core.$ZodIssue` from `@zod/core` instead, especially if you are building a library on top of Zod. */
 export type ZodIssue = core.$ZodIssue;
@@ -21,39 +21,43 @@ export interface ZodError<T = unknown> extends $ZodError<T> {
   isEmpty: boolean;
 }
 
-export const _ZodError: core.$constructor<ZodError> = core.$constructor("ZodError", (inst, issues) => {
-  _$ZodError.init(inst, issues);
-  Object.defineProperty(inst, "format", {
-    value: (mapper: any) => core.formatError(inst, mapper),
-    enumerable: false,
-  });
-  Object.defineProperty(inst, "flatten", {
-    value: (mapper: any) => core.flattenError(inst, mapper),
-    enumerable: false,
-  });
-  Object.defineProperty(inst, "addIssue", {
-    value: (issue: any) => inst.issues.push(issue),
-    enumerable: false,
-  });
-  Object.defineProperty(inst, "addIssues", {
-    value: (issues: any) => inst.issues.push(...issues),
-    enumerable: false,
-  });
-  Object.defineProperty(inst, "isEmpty", {
-    get() {
-      return inst.issues.length === 0;
+const initializer = (inst: ZodError, issues: core.$ZodIssue[]) => {
+  $ZodError.init(inst, issues);
+  Object.defineProperties(inst, {
+    format: {
+      value: (mapper: any) => core.formatError(inst, mapper),
+      // enumerable: false,
+    },
+    flatten: {
+      value: (mapper: any) => core.flattenError(inst, mapper),
+      // enumerable: false,
+    },
+    addIssue: {
+      value: (issue: any) => inst.issues.push(issue),
+      // enumerable: false,
+    },
+    addIssues: {
+      value: (issues: any) => inst.issues.push(...issues),
+      // enumerable: false,
+    },
+    isEmpty: {
+      get() {
+        return inst.issues.length === 0;
+      },
+      // enumerable: false,
     },
   });
+  // Object.defineProperty(inst, "isEmpty", {
+  //   get() {
+  //     return inst.issues.length === 0;
+  //   },
+  // });
+};
+export const ZodError: core.$constructor<ZodError> = core.$constructor("ZodError", initializer);
+export const ZodRealError: core.$constructor<ZodError> = core.$constructor("ZodError", initializer, {
+  Parent: Error,
 });
 
-export interface ZodError<T = unknown> extends $ZodError<T> {}
-export class ZodError extends Error {
-  constructor(issues: core.$ZodIssue[]) {
-    super();
-    _ZodError.init(this, issues);
-  }
-}
-
 export type {
   /** @deprecated Use `z.core.$ZodFlattenedError` instead. */
   $ZodFlattenedError as ZodFlattenedError,
diff --git a/packages/zod/src/v4/classic/parse.ts b/packages/zod/src/v4/classic/parse.ts
index 3c5b4b29..7f8de2a3 100644
--- a/packages/zod/src/v4/classic/parse.ts
+++ b/packages/zod/src/v4/classic/parse.ts
@@ -1,5 +1,5 @@
 import * as core from "zod/v4/core";
-import { ZodError, _ZodError } from "./errors.js";
+import { ZodError, ZodRealError } from "./errors.js";
 
 export type ZodSafeParseResult<T> = ZodSafeParseSuccess<T> | ZodSafeParseError<T>;
 export type ZodSafeParseSuccess<T> = { success: true; data: T; error?: never };
@@ -10,24 +10,24 @@ export const parse: <T extends core.$ZodType>(
   value: unknown,
   _ctx?: core.ParseContext<core.$ZodIssue>,
   _params?: { callee?: core.util.AnyFunc; Err?: core.$ZodErrorClass }
-) => core.output<T> = /* @__PURE__ */ core._parse(ZodError) as any;
+) => core.output<T> = /* @__PURE__ */ core._parse(ZodRealError) as any;
 
 export const parseAsync: <T extends core.$ZodType>(
   schema: T,
   value: unknown,
   _ctx?: core.ParseContext<core.$ZodIssue>,
   _params?: { callee?: core.util.AnyFunc; Err?: core.$ZodErrorClass }
-) => Promise<core.output<T>> = /* @__PURE__ */ core._parseAsync(ZodError) as any;
+) => Promise<core.output<T>> = /* @__PURE__ */ core._parseAsync(ZodRealError) as any;
 
 export const safeParse: <T extends core.$ZodType>(
   schema: T,
   value: unknown,
   _ctx?: core.ParseContext<core.$ZodIssue>
   // _params?: { callee?: core.util.AnyFunc; Err?: core.$ZodErrorClass }
-) => ZodSafeParseResult<core.output<T>> = /* @__PURE__ */ core._safeParse(_ZodError) as any;
+) => ZodSafeParseResult<core.output<T>> = /* @__PURE__ */ core._safeParse(ZodError) as any;
 
 export const safeParseAsync: <T extends core.$ZodType>(
   schema: T,
   value: unknown,
   _ctx?: core.ParseContext<core.$ZodIssue>
-) => Promise<ZodSafeParseResult<core.output<T>>> = /* @__PURE__ */ core._safeParseAsync(_ZodError) as any;
+) => Promise<ZodSafeParseResult<core.output<T>>> = /* @__PURE__ */ core._safeParseAsync(ZodError) as any;
diff --git a/packages/zod/src/v4/classic/schemas.ts b/packages/zod/src/v4/classic/schemas.ts
index 804acee0..a1a0d001 100644
--- a/packages/zod/src/v4/classic/schemas.ts
+++ b/packages/zod/src/v4/classic/schemas.ts
@@ -1044,8 +1044,7 @@ export const ZodArray: core.$constructor<ZodArray> = /*@__PURE__*/ core.$constru
   inst.length = (len, params) => inst.check(checks.length(len, params));
 });
 
-export function array<T extends core.$ZodType>(element: T, params?: string | core.$ZodArrayParams): ZodArray<T>;
-export function array<T extends core.$ZodType>(element: core.$ZodType, params?: any): ZodArray<T> {
+export function array<T extends core.$ZodType>(element: T, params?: string | core.$ZodArrayParams): ZodArray<T> {
   return core._array(ZodArray, element, params) as any;
 }
 
@@ -1056,37 +1055,33 @@ export function keyof<T extends ZodObject>(schema: T): ZodLiteral<keyof T["_zod"
 }
 
 // ZodObject
+
 export interface ZodObject<
   // @ts-ignore cast variance
   out Shape extends core.$ZodShape = core.$ZodLooseShape,
-  OutExtra extends Record<string, unknown> = Record<string, unknown>,
-  InExtra extends Record<string, unknown> = Record<string, unknown>,
+  out Config extends core.$ZodObjectConfig = core.$ZodObjectConfig,
 > extends ZodType {
-  _zod: core.$ZodObjectInternals<Shape, OutExtra, InExtra>;
+  _zod: core.$ZodObjectInternals<Shape, Config>;
   shape: Shape;
 
   keyof(): ZodEnum<util.ToEnum<keyof Shape & string>>;
   /** Define a schema to validate all unrecognized keys. This overrides the existing strict/loose behavior. */
-  catchall<T extends core.$ZodType>(schema: T): ZodObject<Shape, Record<string, T["_zod"]["output"]>>;
+  catchall<T extends core.$ZodType>(schema: T): ZodObject<Shape, core.$catchall<T>>;
 
   /** @deprecated Use `z.looseObject()` or `.loose()` instead. */
-  passthrough(): ZodObject<Shape, Record<string, unknown>>;
+  passthrough(): ZodObject<Shape, core.$loose>;
   /** Consider `z.looseObject(A.shape)` instead */
-  loose(): ZodObject<Shape, Record<string, unknown>>;
+  loose(): ZodObject<Shape, core.$loose>;
 
   /** Consider `z.strictObject(A.shape)` instead */
-  strict(): ZodObject<Shape, {}>;
+  strict(): ZodObject<Shape, core.$strict>;
 
   /** This is the default behavior. This method call is likely unnecessary. */
-  strip(): ZodObject<Shape, {}>;
+  strip(): ZodObject<Shape, core.$strict>;
 
   extend<U extends core.$ZodLooseShape & Partial<Record<keyof Shape, core.$ZodType>>>(
     shape: U
-  ): ZodObject<
-    util.Extend<Shape, U>,
-    OutExtra,
-    InExtra // & B['_zod']["extra"]
-  >;
+  ): ZodObject<util.Extend<Shape, U>, Config>;
 
   /**
    * @deprecated Use destructuring to merge the shapes:
@@ -1098,24 +1093,21 @@ export interface ZodObject<
    * });
    * ```
    */
-  merge<U extends ZodObject>(
-    other: U
-  ): ZodObject<util.Extend<Shape, U["shape"]>, U["_zod"]["outextra"], U["_zod"]["inextra"]>;
+  merge<U extends ZodObject>(other: U): ZodObject<util.Extend<Shape, U["shape"]>, U["_zod"]["config"]>;
 
   pick<M extends util.Exactly<util.Mask<keyof Shape>, M>>(
     mask: M
-  ): ZodObject<util.Flatten<Pick<Shape, Extract<keyof Shape, keyof M>>>, OutExtra, InExtra>;
+  ): ZodObject<util.Flatten<Pick<Shape, Extract<keyof Shape, keyof M>>>, Config>;
 
   omit<M extends util.Exactly<util.Mask<keyof Shape>, M>>(
     mask: M
-  ): ZodObject<util.Flatten<Omit<Shape, Extract<keyof Shape, keyof M>>>, OutExtra, InExtra>;
+  ): ZodObject<util.Flatten<Omit<Shape, Extract<keyof Shape, keyof M>>>, Config>;
 
   partial(): ZodObject<
     {
       [k in keyof Shape]: ZodOptional<Shape[k]>;
     },
-    OutExtra,
-    InExtra
+    Config
   >;
   partial<M extends util.Exactly<util.Mask<keyof Shape>, M>>(
     mask: M
@@ -1123,8 +1115,7 @@ export interface ZodObject<
     {
       [k in keyof Shape]: k extends keyof M ? ZodOptional<Shape[k]> : Shape[k];
     },
-    OutExtra,
-    InExtra
+    Config
   >;
 
   // required
@@ -1132,8 +1123,7 @@ export interface ZodObject<
     {
       [k in keyof Shape]: ZodNonOptional<Shape[k]>;
     },
-    OutExtra,
-    InExtra
+    Config
   >;
   required<M extends util.Exactly<util.Mask<keyof Shape>, M>>(
     mask: M
@@ -1141,8 +1131,7 @@ export interface ZodObject<
     {
       [k in keyof Shape]: k extends keyof M ? ZodNonOptional<Shape[k]> : Shape[k];
     },
-    OutExtra,
-    InExtra
+    Config
   >;
 }
 
@@ -1174,7 +1163,7 @@ export const ZodObject: core.$constructor<ZodObject> = /*@__PURE__*/ core.$const
 export function object<T extends core.$ZodLooseShape = Partial<Record<never, core.$ZodType>>>(
   shape?: T,
   params?: string | core.$ZodObjectParams
-): ZodObject<util.Writeable<T> & {}, {}, {}> {
+): ZodObject<util.Writeable<T> & {}, core.$strip> {
   const def: core.$ZodObjectDef = {
     type: "object",
 
@@ -1193,7 +1182,7 @@ export function object<T extends core.$ZodLooseShape = Partial<Record<never, cor
 export function strictObject<T extends core.$ZodLooseShape>(
   shape: T,
   params?: string | core.$ZodObjectParams
-): ZodObject<T, {}, {}> {
+): ZodObject<T, core.$strict> {
   return new ZodObject({
     type: "object",
 
@@ -1208,10 +1197,11 @@ export function strictObject<T extends core.$ZodLooseShape>(
 }
 
 // looseObject
+
 export function looseObject<T extends core.$ZodLooseShape>(
   shape: T,
   params?: string | core.$ZodObjectParams
-): ZodObject<T, { [k: string]: unknown }, { [k: string]: unknown }> {
+): ZodObject<T, core.$loose> {
   return new ZodObject({
     type: "object",
 
@@ -1614,7 +1604,7 @@ export const ZodTransform: core.$constructor<ZodTransform> = /*@__PURE__*/ core.
           _issue.code ??= "custom";
           _issue.input ??= payload.value;
           _issue.inst ??= inst;
-          _issue.continue ??= !def.abort;
+          _issue.continue ??= true;
           payload.issues.push(util.issue(_issue));
         }
       };
@@ -1633,13 +1623,11 @@ export const ZodTransform: core.$constructor<ZodTransform> = /*@__PURE__*/ core.
 );
 
 export function transform<I = unknown, O = I>(
-  fn: (input: I, ctx: core.ParsePayload) => O,
-  params?: string | core.$ZodTransformParams
+  fn: (input: I, ctx: core.ParsePayload) => O
 ): ZodTransform<Awaited<O>, I> {
   return new ZodTransform({
     type: "transform",
     transform: fn as any,
-    ...util.normalizeParams(params),
   }) as any;
 }
 
@@ -2012,16 +2000,12 @@ export function superRefine<T>(
   return ch;
 }
 
-// instanceof
-abstract class Class {
-  constructor(..._args: any[]) {}
-}
 type ZodInstanceOfParams = util.Params<
   ZodCustom,
   core.$ZodIssueCustom,
   "type" | "check" | "checks" | "fn" | "abort" | "error" | "params" | "path"
 >;
-function _instanceof<T extends typeof Class>(
+function _instanceof<T extends typeof util.Class>(
   cls: T,
   params: ZodInstanceOfParams = {
     error: `Input not instance of ${cls.name}`,
@@ -2064,13 +2048,11 @@ export function json(params?: string | core.$ZodCustomParams): ZodJSONSchema {
 }
 
 // preprocess
-export interface ZodPreprocessParams extends core.$ZodTransformParams {}
 
 // /** @deprecated Use `z.pipe()` and `z.transform()` instead. */
 export function preprocess<A, U extends core.$ZodType>(
   fn: (arg: unknown, ctx: RefinementCtx) => A,
-  schema: U,
-  params?: ZodPreprocessParams
+  schema: U
 ): ZodPipe<ZodTransform<A, unknown>, U> {
-  return pipe(transform(fn as any, params), schema as any);
+  return pipe(transform(fn as any), schema as any);
 }
diff --git a/packages/zod/src/v4/core/api.ts b/packages/zod/src/v4/core/api.ts
index df59752b..663397f8 100644
--- a/packages/zod/src/v4/core/api.ts
+++ b/packages/zod/src/v4/core/api.ts
@@ -988,7 +988,7 @@ export type $ZodArrayParams = util.TypeParams<schemas.$ZodArray, "element">;
 export function _array<T extends schemas.$ZodType>(
   Class: util.SchemaClass<schemas.$ZodArray>,
   element: T,
-  params?: $ZodArrayParams
+  params?: string | $ZodArrayParams
 ): schemas.$ZodArray<T> {
   return new Class({
     type: "array",
@@ -1007,7 +1007,7 @@ export type $ZodUnionParams = util.TypeParams<schemas.$ZodUnion, "options">;
 export function _union<const T extends readonly schemas.$ZodObject[]>(
   Class: util.SchemaClass<schemas.$ZodUnion>,
   options: T,
-  params?: $ZodUnionParams
+  params?: string | $ZodUnionParams
 ): schemas.$ZodUnion<T> {
   return new Class({
     type: "union",
@@ -1028,7 +1028,7 @@ export type $ZodDiscriminatedUnionParams = util.TypeParams<schemas.$ZodDiscrimin
 export function _discriminatedUnion<Types extends [$ZodTypeDiscriminable, ...$ZodTypeDiscriminable[]]>(
   Class: util.SchemaClass<schemas.$ZodDiscriminatedUnion>,
   options: Types,
-  params?: $ZodDiscriminatedUnionParams
+  params?: string | $ZodDiscriminatedUnionParams
 ): schemas.$ZodDiscriminatedUnion<Types> {
   return new Class({
     type: "union",
@@ -1056,24 +1056,24 @@ export type $ZodTupleParams = util.TypeParams<schemas.$ZodTuple, "items" | "rest
 export function _tuple<T extends readonly [schemas.$ZodType, ...schemas.$ZodType[]]>(
   Class: util.SchemaClass<schemas.$ZodTuple>,
   items: T,
-  params?: $ZodTupleParams
+  params?: string | $ZodTupleParams
 ): schemas.$ZodTuple<T, null>;
 export function _tuple<T extends readonly [schemas.$ZodType, ...schemas.$ZodType[]], Rest extends schemas.$ZodType>(
   Class: util.SchemaClass<schemas.$ZodTuple>,
   items: T,
   rest: Rest,
-  params?: $ZodTupleParams
+  params?: string | $ZodTupleParams
 ): schemas.$ZodTuple<T, Rest>;
 // export function _tuple(
 //   Class: util.SchemaClass<schemas.$ZodTuple>,
 //   items: [],
-//   params?: $ZodTupleParams
+//   params?: string | $ZodTupleParams
 // ): schemas.$ZodTuple<[], null>;
 export function _tuple(
   Class: util.SchemaClass<schemas.$ZodTuple>,
   items: schemas.$ZodType[],
-  _paramsOrRest?: $ZodTupleParams | schemas.$ZodType,
-  _params?: $ZodTupleParams
+  _paramsOrRest?: string | $ZodTupleParams | schemas.$ZodType,
+  _params?: string | $ZodTupleParams
 ) {
   const hasRest = _paramsOrRest instanceof schemas.$ZodType;
   const params = hasRest ? _params : _paramsOrRest;
@@ -1092,7 +1092,7 @@ export function _record<Key extends schemas.$ZodRecordKey, Value extends schemas
   Class: util.SchemaClass<schemas.$ZodRecord>,
   keyType: Key,
   valueType: Value,
-  params?: $ZodRecordParams
+  params?: string | $ZodRecordParams
 ): schemas.$ZodRecord<Key, Value> {
   return new Class({
     type: "record",
@@ -1108,7 +1108,7 @@ export function _map<Key extends schemas.$ZodObject, Value extends schemas.$ZodO
   Class: util.SchemaClass<schemas.$ZodMap>,
   keyType: Key,
   valueType: Value,
-  params?: $ZodMapParams
+  params?: string | $ZodMapParams
 ): schemas.$ZodMap<Key, Value> {
   return new Class({
     type: "map",
@@ -1123,7 +1123,7 @@ export type $ZodSetParams = util.TypeParams<schemas.$ZodSet, "valueType">;
 export function _set<Value extends schemas.$ZodObject>(
   Class: util.SchemaClass<schemas.$ZodSet>,
   valueType: Value,
-  params?: $ZodSetParams
+  params?: string | $ZodSetParams
 ): schemas.$ZodSet<Value> {
   return new Class({
     type: "set",
@@ -1137,14 +1137,14 @@ export type $ZodEnumParams = util.TypeParams<schemas.$ZodEnum, "entries">;
 export function _enum<const T extends string[]>(
   Class: util.SchemaClass<schemas.$ZodEnum>,
   values: T,
-  params?: $ZodEnumParams
+  params?: string | $ZodEnumParams
 ): schemas.$ZodEnum<util.ToEnum<T[number]>>;
 export function _enum<T extends util.EnumLike>(
   Class: util.SchemaClass<schemas.$ZodEnum>,
   entries: T,
-  params?: $ZodEnumParams
+  params?: string | $ZodEnumParams
 ): schemas.$ZodEnum<T>;
-export function _enum(Class: util.SchemaClass<schemas.$ZodEnum>, values: any, params?: $ZodEnumParams) {
+export function _enum(Class: util.SchemaClass<schemas.$ZodEnum>, values: any, params?: string | $ZodEnumParams) {
   const entries: any = Array.isArray(values) ? Object.fromEntries(values.map((v) => [v, v])) : values;
   // if (Array.isArray(values)) {
   //   for (const value of values) {
@@ -1175,7 +1175,7 @@ export function _enum(Class: util.SchemaClass<schemas.$ZodEnum>, values: any, pa
 export function _nativeEnum<T extends util.EnumLike>(
   Class: util.SchemaClass<schemas.$ZodEnum>,
   entries: T,
-  params?: $ZodEnumParams
+  params?: string | $ZodEnumParams
 ): schemas.$ZodEnum<T> {
   return new Class({
     type: "enum",
@@ -1189,12 +1189,12 @@ export type $ZodLiteralParams = util.TypeParams<schemas.$ZodLiteral, "values">;
 export function _literal<const T extends Array<util.Literal>>(
   Class: util.SchemaClass<schemas.$ZodLiteral>,
   value: T,
-  params?: $ZodLiteralParams
+  params?: string | $ZodLiteralParams
 ): schemas.$ZodLiteral<T[number]>;
 export function _literal<const T extends util.Literal>(
   Class: util.SchemaClass<schemas.$ZodLiteral>,
   value: T,
-  params?: $ZodLiteralParams
+  params?: string | $ZodLiteralParams
 ): schemas.$ZodLiteral<T>;
 export function _literal(Class: util.SchemaClass<schemas.$ZodLiteral>, value: any, params: any) {
   return new Class({
@@ -1217,13 +1217,11 @@ export function _file(Class: util.SchemaClass<schemas.$ZodFile>, params?: string
 export type $ZodTransformParams = util.TypeParams<schemas.$ZodTransform, "transform">;
 export function _transform<I = unknown, O = I>(
   Class: util.SchemaClass<schemas.$ZodTransform>,
-  fn: (input: I, ctx?: schemas.ParsePayload) => O,
-  params?: $ZodTransformParams
+  fn: (input: I, ctx?: schemas.ParsePayload) => O
 ): schemas.$ZodTransform<Awaited<O>, I> {
   return new Class({
     type: "transform",
     transform: fn as any,
-    ...util.normalizeParams(params),
   }) as any;
 }
 
@@ -1272,7 +1270,7 @@ export type $ZodNonOptionalParams = util.TypeParams<schemas.$ZodNonOptional, "in
 export function _nonoptional<T extends schemas.$ZodObject>(
   Class: util.SchemaClass<schemas.$ZodNonOptional>,
   innerType: T,
-  params?: $ZodNonOptionalParams
+  params?: string | $ZodNonOptionalParams
 ): schemas.$ZodNonOptional<T> {
   return new Class({
     type: "nonoptional",
@@ -1341,7 +1339,7 @@ export type $ZodTemplateLiteralParams = util.TypeParams<schemas.$ZodTemplateLite
 export function _templateLiteral<const Parts extends schemas.$TemplateLiteralPart[]>(
   Class: util.SchemaClass<schemas.$ZodTemplateLiteral>,
   parts: Parts,
-  params?: $ZodTemplateLiteralParams
+  params?: string | $ZodTemplateLiteralParams
 ): schemas.$ZodTemplateLiteral<schemas.$PartsToTemplateLiteral<Parts>> {
   return new Class({
     type: "template_literal",
@@ -1421,7 +1419,7 @@ export function _stringbool(
     Boolean?: typeof schemas.$ZodBoolean;
     Unknown?: typeof schemas.$ZodUnknown;
   },
-  _params?: $ZodStringBoolParams
+  _params?: string | $ZodStringBoolParams
 ): schemas.$ZodPipe<schemas.$ZodUnknown, schemas.$ZodBoolean<boolean>> {
   const params = util.normalizeParams(_params);
   const trueValues = new Set(params?.truthy ?? ["true", "1", "yes", "on", "y", "enabled"]);
diff --git a/packages/zod/src/v4/core/core.ts b/packages/zod/src/v4/core/core.ts
index a523da9e..707c5a05 100644
--- a/packages/zod/src/v4/core/core.ts
+++ b/packages/zod/src/v4/core/core.ts
@@ -1,5 +1,6 @@
 import type * as errors from "./errors.js";
 import type * as schemas from "./schemas.js";
+import type { Class } from "./util.js";
 //////////////////////////////   CONSTRUCTORS   ///////////////////////////////////////
 
 type ZodTrait = { _zod: { def: any; [k: string]: any } };
@@ -10,10 +11,14 @@ export interface $constructor<T extends ZodTrait, D = T["_zod"]["def"]> {
 
 export /*@__NO_SIDE_EFFECTS__*/ function $constructor<T extends ZodTrait, D = T["_zod"]["def"]>(
   name: string,
-  initializer: (inst: T, def: D) => void
+  initializer: (inst: T, def: D) => void,
+  params?: { Parent?: typeof Class }
 ): $constructor<T, D> {
-  class _ {
+  const Parent = params?.Parent ?? Object;
+
+  class _ extends Parent {
     constructor(def: D) {
+      super();
       const th = this as any;
       _.init(th, def);
       th._zod.deferred ??= [];
@@ -22,7 +27,11 @@ export /*@__NO_SIDE_EFFECTS__*/ function $constructor<T extends ZodTrait, D = T[
       }
     }
     static init(inst: T, def: D) {
-      inst._zod ??= {} as any;
+      Object.defineProperty(inst, "_zod", {
+        value: inst._zod ?? {},
+        enumerable: false,
+      });
+      // inst._zod ??= {} as any;
       inst._zod.traits ??= new Set();
       // const seen = inst._zod.traits.has(name);
 
@@ -36,7 +45,8 @@ export /*@__NO_SIDE_EFFECTS__*/ function $constructor<T extends ZodTrait, D = T[
       inst._zod.def = def;
     }
 
-    static [Symbol.hasInstance](inst: any) {
+    static override [Symbol.hasInstance](inst: any) {
+      if (params?.Parent && inst instanceof params.Parent) return true;
       return inst?._zod?.traits?.has(name);
     }
   }
diff --git a/packages/zod/src/v4/core/doc.ts b/packages/zod/src/v4/core/doc.ts
index ffb7bd72..55e7c4fb 100644
--- a/packages/zod/src/v4/core/doc.ts
+++ b/packages/zod/src/v4/core/doc.ts
@@ -34,9 +34,10 @@ export class Doc {
   }
 
   compile() {
+    const F = Function;
     const args = this?.args;
     const content = this?.content ?? [``];
     const lines = [...content.map((x) => `  ${x}`)];
-    return new Function(...args, lines.join("\n"));
+    return new F(...args, lines.join("\n"));
   }
 }
diff --git a/packages/zod/src/v4/core/errors.ts b/packages/zod/src/v4/core/errors.ts
index 024bd978..886f555a 100644
--- a/packages/zod/src/v4/core/errors.ts
+++ b/packages/zod/src/v4/core/errors.ts
@@ -180,59 +180,33 @@ export interface $ZodError<T = unknown> extends Error {
   name: string;
 }
 
-export const _$ZodError: $constructor<$ZodError> = $constructor("$ZodError", (inst, def) => {
-  Object.defineProperties(inst, {
-    issues: {
-      value: def,
-      enumerable: true,
-    },
-    _zod: {
-      value: inst._zod,
-      enumerable: false,
-    },
-    // message: {
-    //   get() {
-    //     return JSON.stringify(this.issues, util.jsonStringifyReplacer, 2);
-    //   },
-    //   enumerable: false,
-    // },
+const initializer = (inst: $ZodError, def: $ZodIssue[]): void => {
+  Object.defineProperty(inst, "_zod", {
+    value: inst._zod,
+    enumerable: false,
   });
-});
-
-// export interface $ZodError<T = unknown> extends $ZodError<T> {}
-export class $ZodError extends Error {
-  constructor(issues: $ZodIssue[]) {
-    super();
-    _$ZodError.init(this, issues);
-  }
-}
+  Object.defineProperty(inst, "issues", {
+    value: def,
+    enumerable: true,
+  });
+  // Object.defineProperty(inst, "message", {
+  //   get() {
+  //     return (
+  //       "\n" +
+  //       inst.issues
+  //         .map((iss) => {
+  //           return `✖ ${iss.message}${iss.path.length ? ` [${iss.path.join(".")}]` : ""}`;
+  //         })
+  //         .join("\n")
+  //     );
+  //   },
+  //   enumerable: false,
+  // });
+};
 
-// export class _$ZodError extends Error {
-//   public issues!: $ZodIssue[];
-
-//   override get message() {
-//     // console.log("GET MESSAGE");
-//     return JSON.stringify(this.issues, jsonStringifyReplacer, 2);
-//   }
-
-//   // toString() {
-//   //   console.log("TO STRING");
-//   //   return this.stack;
-//   // }
-//   constructor(issues: $ZodIssue[]) {
-//     super();
-//     Object.defineProperty(this, "_tag", { value: ZOD_ERROR, enumerable: false });
-//     // Object.defineProperty(this, "name", { value: "$ZodError", enumerable: false });
-//     // Object.defineProperty(this, "message", { value: JSON.stringify(issues, jsonStringifyReplacer, 2) });
-//     // this.issues = issues;
-//     Object.defineProperty(this, "issues", { value: issues, enumerable: false });
-//   }
-
-//   // @ts-ignore
-//   static [Symbol.hasInstance](inst: any) {
-//     return inst?._tag === ZOD_ERROR;
-//   }
-// }
+export const $ZodError: $constructor<$ZodError> = $constructor("$ZodError", initializer);
+interface $ZodRealError<T = any> extends $ZodError<T> {}
+export const $ZodRealError: $constructor<$ZodRealError> = $constructor("$ZodError", initializer, { Parent: Error });
 
 ///////////////////    ERROR UTILITIES   ////////////////////////
 
@@ -317,24 +291,6 @@ export function formatError<T>(error: $ZodError, _mapper?: any) {
   return fieldErrors;
 }
 
-type _ZodErrorTree<T, U = string> = T extends [any, ...any[]]
-  ? { [K in keyof T]?: $ZodFormattedError<T[K], U> }
-  : T extends any[]
-    ? { [k: number]: $ZodFormattedError<T[number], U> }
-    : T extends object
-      ? util.Flatten<{ [K in keyof T]?: $ZodFormattedError<T[K], U> }>
-      : any;
-
-// export type $ZodErrorTree<T, U = string> = {
-//   errors: U[];
-//   properties: T extends [any, ...any[]]
-//     ? { [K in keyof T]?: $ZodErrorTree<T[K], U> }
-//     : T extends any[]
-//       ? Array<$ZodErrorTree<T[number], U>>
-//       : T extends object
-//         ? { [K in keyof T]?: $ZodErrorTree<T[K], U> }
-//         : any;
-// };
 export type $ZodErrorTree<T, U = string> = T extends [any, ...any[]]
   ? { errors: U[]; items?: { [K in keyof T]?: $ZodErrorTree<T[K], U> } }
   : T extends any[]
@@ -352,24 +308,27 @@ export function treeifyError<T>(error: $ZodError, _mapper?: any) {
       return issue.message;
     };
   const result: $ZodErrorTree<T> = { errors: [] } as any;
-  const processError = (error: { issues: $ZodIssue[] }) => {
+  const processError = (error: { issues: $ZodIssue[] }, path: PropertyKey[] = []) => {
     for (const issue of error.issues) {
       if (issue.code === "invalid_union") {
-        issue.errors.map((issues) => processError({ issues }));
+        issue.errors.map((issues) => processError({ issues }, issue.path));
       } else if (issue.code === "invalid_key") {
-        processError({ issues: issue.issues });
+        processError({ issues: issue.issues }, issue.path);
       } else if (issue.code === "invalid_element") {
-        processError({ issues: issue.issues });
-      } else if (issue.path.length === 0) {
-        result.errors.push(mapper(issue));
+        processError({ issues: issue.issues }, issue.path);
       } else {
+        const fullpath = [...path, ...issue.path];
+        if (fullpath.length === 0) {
+          result.errors.push(mapper(issue));
+          continue;
+        }
+
         let curr: any = result;
         let i = 0;
+        while (i < fullpath.length) {
+          const el = fullpath[i];
 
-        while (i < issue.path.length) {
-          const el = issue.path[i];
-
-          const terminal = i === issue.path.length - 1;
+          const terminal = i === fullpath.length - 1;
           if (typeof el === "string") {
             curr.properties ??= {};
             curr.properties[el] ??= { errors: [] };
@@ -383,27 +342,7 @@ export function treeifyError<T>(error: $ZodError, _mapper?: any) {
           if (terminal) {
             curr.errors.push(mapper(issue));
           }
-          // curr = curr.properties[el];
-          // const terminal = i === issue.path.length - 1;
-
-          // if (!curr) {
-          //   if (typeof el === "string") {
-          //     result.properties = {};
-          //   } else {
-          //     (result as any).properties = [];
-          //   }
-          // }
-
-          // // const curr: any = result.properties;
-          // if (!terminal) {
-          //   curr[el] = curr[el] || { errors: [] };
-          // } else {
-          //   curr[el] = curr[el] || { errors: [] };
-          //   curr[el].errors.push(mapper(issue));
-          // }
-
-          // curr = curr[el];
-          // curr = curr.properties[el];
+
           i++;
         }
       }
diff --git a/packages/zod/src/v4/core/json-schema.ts b/packages/zod/src/v4/core/json-schema.ts
index 3997b3dd..bbcafdca 100644
--- a/packages/zod/src/v4/core/json-schema.ts
+++ b/packages/zod/src/v4/core/json-schema.ts
@@ -9,8 +9,6 @@ export type Schema =
 // | BaseSchema;
 
 export interface BaseSchema {
-  /** A special key used as an intermediate representation of extends-style relationships. Omitted as a $ref with additional properties. */
-  _ref?: BaseSchema;
   type?: string | undefined;
   $id?: string | undefined;
   id?: string | undefined;
@@ -37,6 +35,10 @@ export interface BaseSchema {
   enum?: Array<string | number | boolean | null> | undefined;
   const?: string | number | boolean | null | undefined;
   [k: string]: unknown;
+
+  /** A special key used as an intermediate representation of extends-style relationships. Omitted as a $ref with additional properties. */
+  // _ref?: BaseSchema;
+  _prefault?: unknown | undefined;
 }
 
 export interface ObjectSchema extends BaseSchema {
diff --git a/packages/zod/src/v4/core/parse.ts b/packages/zod/src/v4/core/parse.ts
index 6d01de16..31a9e290 100644
--- a/packages/zod/src/v4/core/parse.ts
+++ b/packages/zod/src/v4/core/parse.ts
@@ -27,7 +27,7 @@ export const _parse: (_Err: $ZodErrorClass) => $Parse = (_Err) => (schema, value
   return result.value;
 };
 
-export const parse: $Parse = /* @__PURE__*/ _parse(errors.$ZodError);
+export const parse: $Parse = /* @__PURE__*/ _parse(errors.$ZodRealError);
 
 export type $ParseAsync = <T extends schemas.$ZodType>(
   schema: T,
@@ -48,7 +48,7 @@ export const _parseAsync: (_Err: $ZodErrorClass) => $ParseAsync = (_Err) => asyn
   return result.value as core.output<typeof schema>;
 };
 
-export const parseAsync: $ParseAsync = /* @__PURE__*/ _parseAsync(errors.$ZodError);
+export const parseAsync: $ParseAsync = /* @__PURE__*/ _parseAsync(errors.$ZodRealError);
 
 export type $SafeParse = <T extends schemas.$ZodType>(
   schema: T,
@@ -70,7 +70,7 @@ export const _safeParse: (_Err: $ZodErrorClass) => $SafeParse = (_Err) => (schem
       }
     : { success: true, data: result.value };
 };
-export const safeParse: $SafeParse = /* @__PURE__*/ _safeParse(errors._$ZodError);
+export const safeParse: $SafeParse = /* @__PURE__*/ _safeParse(errors.$ZodError);
 
 export type $SafeParseAsync = <T extends schemas.$ZodType>(
   schema: T,
@@ -91,4 +91,4 @@ export const _safeParseAsync: (_Err: $ZodErrorClass) => $SafeParseAsync = (_Err)
     : { success: true, data: result.value };
 };
 
-export const safeParseAsync: $SafeParseAsync = /* @__PURE__*/ _safeParseAsync(errors._$ZodError);
+export const safeParseAsync: $SafeParseAsync = /* @__PURE__*/ _safeParseAsync(errors.$ZodError);
diff --git a/packages/zod/src/v4/core/regexes.ts b/packages/zod/src/v4/core/regexes.ts
index e4a25296..e6a37994 100644
--- a/packages/zod/src/v4/core/regexes.ts
+++ b/packages/zod/src/v4/core/regexes.ts
@@ -67,8 +67,8 @@ export const cidrv6: RegExp =
 export const ip: RegExp = new RegExp(`(${ipv4.source})|(${ipv6.source})`);
 
 // https://stackoverflow.com/questions/7860392/determine-if-string-is-in-base64-using-javascript
-export const base64: RegExp = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;
-export const base64url: RegExp = /^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$/;
+export const base64: RegExp = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
+export const base64url: RegExp = /^[A-Za-z0-9_-]*$/;
 
 // based on https://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address
 // export const hostname: RegExp =
diff --git a/packages/zod/src/v4/core/schemas.ts b/packages/zod/src/v4/core/schemas.ts
index 11b348ea..34acf032 100644
--- a/packages/zod/src/v4/core/schemas.ts
+++ b/packages/zod/src/v4/core/schemas.ts
@@ -810,6 +810,16 @@ export const $ZodCIDRv6: core.$constructor<$ZodCIDRv6> = /*@__PURE__*/ core.$con
 // });
 
 //////////////////////////////   ZodBase64   //////////////////////////////
+export function isValidBase64(data: string): boolean {
+  if (data === "") return true;
+  if (data.length % 4 !== 0) return false;
+  try {
+    atob(data);
+    return true;
+  } catch {
+    return false;
+  }
+}
 
 export interface $ZodBase64Def extends $ZodStringFormatDef<"base64"> {}
 export interface $ZodBase64Internals extends $ZodStringFormatInternals<"base64"> {}
@@ -827,10 +837,27 @@ export const $ZodBase64: core.$constructor<$ZodBase64> = /*@__PURE__*/ core.$con
     inst._zod.onattach.push((inst) => {
       inst._zod.computed.contentEncoding = "base64";
     });
+
+    inst._zod.check = (payload) => {
+      if (isValidBase64(payload.value)) return;
+
+      payload.issues.push({
+        code: "invalid_format",
+        format: "base64",
+        input: payload.value,
+        inst,
+      });
+    };
   }
 );
 
 //////////////////////////////   ZodBase64   //////////////////////////////
+export function isValidBase64URL(data: string): boolean {
+  if (!regexes.base64url.test(data)) return false;
+  const base64 = data.replace(/[-_]/g, (c) => (c === "-" ? "+" : "/"));
+  const padded = base64.padEnd(Math.ceil(base64.length / 4) * 4, "=");
+  return isValidBase64(padded);
+}
 
 export interface $ZodBase64URLDef extends $ZodStringFormatDef<"base64url"> {}
 export interface $ZodBase64URLInternals extends $ZodStringFormatInternals<"base64url"> {}
@@ -848,6 +875,17 @@ export const $ZodBase64URL: core.$constructor<$ZodBase64URL> = /*@__PURE__*/ cor
     inst._zod.onattach.push((inst) => {
       inst._zod.computed.contentEncoding = "base64url";
     });
+
+    inst._zod.check = (payload) => {
+      if (isValidBase64URL(payload.value)) return;
+
+      payload.issues.push({
+        code: "invalid_format",
+        format: "base64url",
+        input: payload.value,
+        inst,
+      });
+    };
   }
 );
 
@@ -1527,20 +1565,18 @@ export interface $ZodObjectDef<Shape extends $ZodShape = $ZodShape> extends $Zod
 export interface $ZodObjectInternals<
   // @ts-ignore Cast variance
   out Shape extends Readonly<$ZodShape> = Readonly<$ZodShape>,
-  out OutExtra extends Record<string, unknown> = Record<string, unknown>,
-  out InExtra extends Record<string, unknown> = Record<string, unknown>,
+  out Config extends $ZodObjectConfig = $ZodObjectConfig,
 > extends $ZodTypeInternals<any, any> {
   def: $ZodObjectDef<Shape>;
-  outextra: OutExtra;
-  inextra: InExtra;
+  config: Config;
   isst: errors.$ZodIssueInvalidType | errors.$ZodIssueUnrecognizedKeys;
   disc: util.DiscriminatorMap;
 
   // special keys only used for objects
   // not defined on $ZodTypeInternals (base interface) because it breaks cyclical inference
   // the z.infer<> util checks for these first when extracting inferred type
-  "~output": $InferObjectOutput<Shape, OutExtra>;
-  "~input": $InferObjectInput<Shape, InExtra>;
+  "~output": $InferObjectOutput<Shape, Config["out"]>;
+  "~input": $InferObjectInput<Shape, Config["in"]>;
 }
 export type $ZodLooseShape = Record<string, any>;
 
@@ -1549,26 +1585,25 @@ type OptionalInSchema = { _zod: { optionality: "defaulted" | "optional" } };
 
 export type $InferObjectOutput<T extends $ZodLooseShape, Extra extends Record<string, unknown>> = string extends keyof T
   ? object
-  : keyof T extends never
+  : keyof (T & Extra) extends never
     ? Record<string, never>
     : util.Prettify<
         {
           -readonly [k in keyof T as T[k] extends OptionalOutSchema ? never : k]: core.output<T[k]>;
         } & {
           -readonly [k in keyof T as T[k] extends OptionalOutSchema ? k : never]?: core.output<T[k]>;
-        }
-      > &
-        Extra;
+        } & Extra
+      >;
 
 export type $InferObjectInput<T extends $ZodLooseShape, Extra extends Record<string, unknown>> = string extends keyof T
   ? object
-  : keyof T extends never
+  : keyof (T & Extra) extends never
     ? Record<string, never>
     : util.Prettify<
         {
-          [k in keyof T as T[k] extends OptionalInSchema ? never : k]: core.input<T[k]>;
+          -readonly [k in keyof T as T[k] extends OptionalInSchema ? never : k]: core.input<T[k]>;
         } & {
-          [k in keyof T as T[k] extends OptionalInSchema ? k : never]?: core.input<T[k]>;
+          -readonly [k in keyof T as T[k] extends OptionalInSchema ? k : never]?: core.input<T[k]>;
         } & Extra
       >;
 
@@ -1603,13 +1638,32 @@ function handleOptionalObjectResult(result: ParsePayload, final: ParsePayload, k
   }
 }
 
+export type $ZodObjectConfig = { out: Record<string, unknown>; in: Record<string, unknown> };
+
+export type $loose = {
+  out: Record<string, unknown>;
+  in: Record<string, unknown>;
+};
+export type $strict = {
+  out: {};
+  in: {};
+};
+export type $strip = {
+  out: {};
+  in: {};
+};
+export type $catchall<T extends $ZodType> = {
+  out: { [k: string]: core.output<T> };
+  in: { [k: string]: core.input<T> };
+};
 export interface $ZodObject<
   // @ts-ignore Cast variance
   out Shape extends Readonly<$ZodShape> = Readonly<$ZodShape>,
-  out OutExtra extends Record<string, unknown> = Record<string, unknown>,
-  out InExtra extends Record<string, unknown> = Record<string, unknown>,
+  out Params extends $ZodObjectConfig = $ZodObjectConfig,
+  // out OutExtra extends Record<string, unknown> = Record<string, unknown>,
+  // out InExtra extends Record<string, unknown> = Record<string, unknown>,
 > extends $ZodType {
-  _zod: $ZodObjectInternals<Shape, OutExtra, InExtra>;
+  _zod: $ZodObjectInternals<Shape, Params>;
 }
 
 export const $ZodObject: core.$constructor<$ZodObject> = /*@__PURE__*/ core.$constructor("$ZodObject", (inst, def) => {
@@ -1941,21 +1995,30 @@ export interface $ZodDiscriminatedUnion<T extends readonly $ZodType[] = readonly
   _zod: $ZodDiscriminatedUnionInternals<T>;
 }
 
+function matchDiscriminatorAtKey(input: any, key: PropertyKey, disc: util.DiscriminatorMapElement): boolean {
+  let matched = true;
+  const data = input?.[key];
+
+  if (disc.values.size && !disc.values.has(data)) {
+    matched = false;
+  }
+  if (disc.maps.length > 0) {
+    for (const m of disc.maps) {
+      if (!matchDiscriminators(data, m)) {
+        matched = false;
+      }
+    }
+  }
+
+  return matched;
+}
+
 function matchDiscriminators(input: any, discs: util.DiscriminatorMap): boolean {
   let matched = true;
   for (const [key, value] of discs) {
-    const data = input?.[key];
-
-    if (value.values.size && !value.values.has(data)) {
+    if (!matchDiscriminatorAtKey(input, key, value)) {
       matched = false;
     }
-    if (value.maps.length > 0) {
-      for (const m of value.maps) {
-        if (!matchDiscriminators(data, m)) {
-          matched = false;
-        }
-      }
-    }
   }
 
   return matched;
@@ -1969,8 +2032,9 @@ export const $ZodDiscriminatedUnion: core.$constructor<$ZodDiscriminatedUnion> =
     const _super = inst._zod.parse;
     const _disc: util.DiscriminatorMap = new Map();
     for (const el of def.options) {
-      if (!el._zod.disc) throw new Error(`Invalid discriminated union option at index "${def.options.indexOf(el)}"`);
-      for (const [key, o] of el._zod.disc) {
+      const subdisc = el._zod.disc;
+      if (!subdisc) throw new Error(`Invalid discriminated union option at index "${def.options.indexOf(el)}"`);
+      for (const [key, o] of subdisc) {
         if (!_disc.has(key))
           _disc.set(key, {
             values: new Set(),
@@ -1987,13 +2051,10 @@ export const $ZodDiscriminatedUnion: core.$constructor<$ZodDiscriminatedUnion> =
     }
     inst._zod.disc = _disc;
 
-    const discMap: Map<$ZodType, util.DiscriminatorMap> = new Map();
-    for (const option of def.options) {
-      const disc = option._zod.disc;
-      if (!disc) {
-        throw new Error(`Invalid discriminated union element: ${option._zod.def.type}`);
-      }
-      discMap.set(option, disc);
+    const subdiscs = def.options.map((o) => o._zod.disc!);
+    const discKeys = [...inst._zod.disc.keys()].filter((k) => subdiscs.every((d) => d.has(k)));
+    if (discKeys.length === 0) {
+      throw new Error(`Invalid discriminated union: no shared discriminator key: ${discKeys.join(", ")}`);
     }
 
     inst._zod.parse = (payload, ctx) => {
@@ -2009,15 +2070,24 @@ export const $ZodDiscriminatedUnion: core.$constructor<$ZodDiscriminatedUnion> =
       }
 
       const filteredOptions: $ZodType[] = [];
-      for (const option of def.options) {
-        if (discMap.has(option)) {
-          if (matchDiscriminators(input, discMap.get(option)!)) {
+      for (const k of discKeys) {
+        let matched = false;
+        for (const option of def.options) {
+          if (matchDiscriminatorAtKey(input, k, option._zod.disc!.get(k)!)) {
+            matched = true;
             filteredOptions.push(option);
           }
-        } else {
-          // no discriminator
-          filteredOptions.push(option);
         }
+        // no matching discriminator
+        if (!matched && !def.unionFallback)
+          payload.issues.push({
+            code: "invalid_union",
+            errors: [],
+            note: "No matching discriminator",
+            path: [k],
+            input,
+            inst,
+          });
       }
 
       if (filteredOptions.length === 1) return filteredOptions[0]._zod.run(payload, ctx) as any;
@@ -2025,13 +2095,7 @@ export const $ZodDiscriminatedUnion: core.$constructor<$ZodDiscriminatedUnion> =
       if (def.unionFallback) {
         return _super(payload, ctx);
       }
-      payload.issues.push({
-        code: "invalid_union",
-        errors: [],
-        note: "No matching discriminator",
-        input,
-        inst,
-      });
+
       return payload;
     };
   });
@@ -2632,7 +2696,7 @@ function handleSetResult(result: ParsePayload, final: ParsePayload<Set<any>>) {
 ////////////////////////////////////////
 ////////////////////////////////////////
 export type $InferEnumOutput<T extends util.EnumLike> = T[keyof T] & {};
-export type $InferEnumInput<T extends util.EnumLike> = $InferEnumOutput<T>;
+export type $InferEnumInput<T extends util.EnumLike> = T[keyof T] & {};
 
 export interface $ZodEnumDef<T extends util.EnumLike = util.EnumLike> extends $ZodTypeDef {
   type: "enum";
@@ -2832,7 +2896,6 @@ export const $ZodFile: core.$constructor<$ZodFile> = /*@__PURE__*/ core.$constru
 export interface $ZodTransformDef extends $ZodTypeDef {
   type: "transform";
   transform: (input: unknown, payload: ParsePayload<unknown>) => util.MaybeAsync<unknown>;
-  abort?: boolean | undefined;
 }
 export interface $ZodTransformInternals<O = unknown, I = unknown> extends $ZodTypeInternals<O, I> {
   def: $ZodTransformDef;
@@ -3246,6 +3309,7 @@ export const $ZodCatch: core.$constructor<$ZodCatch> = /*@__PURE__*/ core.$const
     const result = def.innerType._zod.run(payload, ctx);
     if (result instanceof Promise) {
       return result.then((result) => {
+        payload.value = result.value;
         if (result.issues.length) {
           payload.value = def.catchValue({
             ...payload,
@@ -3256,12 +3320,12 @@ export const $ZodCatch: core.$constructor<$ZodCatch> = /*@__PURE__*/ core.$const
           });
           payload.issues = [];
         }
-        payload.value = result.value;
 
         return payload;
       });
     }
 
+    payload.value = result.value;
     if (result.issues.length) {
       payload.value = def.catchValue({
         ...payload,
@@ -3272,7 +3336,6 @@ export const $ZodCatch: core.$constructor<$ZodCatch> = /*@__PURE__*/ core.$const
       });
       payload.issues = [];
     }
-    payload.value = result.value;
 
     return payload;
   };
diff --git a/packages/zod/src/v4/core/to-json-schema.ts b/packages/zod/src/v4/core/to-json-schema.ts
index 19f2e919..97482c99 100644
--- a/packages/zod/src/v4/core/to-json-schema.ts
+++ b/packages/zod/src/v4/core/to-json-schema.ts
@@ -26,7 +26,6 @@ interface JSONSchemaGeneratorParams {
 interface ProcessParams {
   schemaPath: schemas.$ZodType[];
   path: (string | number)[];
-  // initial?: Seen | undefined;
 }
 
 interface EmitParams {
@@ -34,21 +33,16 @@ interface EmitParams {
    * - `"ref"` — Default. Cycles will be broken using $defs
    * - `"throw"` — Cycles will throw an error if encountered */
   cycles?: "ref" | "throw";
-
   /* How to handle reused schemas.
    * - `"inline"` — Default. Reused schemas will be inlined
    * - `"ref"` — Reused schemas will be extracted as $defs */
   reused?: "ref" | "inline";
-  /** A function used to convert `id` values to URIs to be used in *external* $refs.
-   *
-   * Default is `(id) => id`.
-   */
-  // uri?: (id: string) => string;
+
   external?:
     | {
+        /**  */
         registry: $ZodRegistry<{ id?: string | undefined }>;
         uri: (id: string) => string;
-        // __shared: boolean;
         defs: Record<string, JSONSchema.BaseSchema>;
       }
     | undefined;
@@ -71,8 +65,8 @@ interface Seen {
   count: number;
   /** Cycle path */
   cycle?: (string | number)[] | undefined;
-
-  // external?: string | undefined;
+  isParent?: boolean | undefined;
+  ref?: schemas.$ZodType | undefined | null;
 }
 
 export class JSONSchemaGenerator {
@@ -86,7 +80,6 @@ export class JSONSchemaGenerator {
   seen: Map<schemas.$ZodType, Seen>;
 
   constructor(params?: JSONSchemaGeneratorParams) {
-    // this.external = params?.external;
     this.metadataRegistry = params?.metadata ?? globalRegistry;
     this.target = params?.target ?? "draft-2020-12";
     this.unrepresentable = params?.unrepresentable ?? "throw";
@@ -98,13 +91,6 @@ export class JSONSchemaGenerator {
 
   process(schema: schemas.$ZodType, _params: ProcessParams = { path: [], schemaPath: [] }): JSONSchema.BaseSchema {
     const def = (schema as schemas.$ZodTypes)._zod.def;
-    // if (def.type === "lazy") {
-    //   return this.process((schema as schemas.$ZodLazy)._zod._getter, _params);
-    // } else if (def.type === "promise") {
-    //   return this.process(def.innerType, _params);
-    // } else if (def.type === "pipe") {
-    //   return this.process(def.out, _params);
-    // }
 
     // check for schema in seens
     const seen = this.seen.get(schema);
@@ -127,15 +113,9 @@ export class JSONSchemaGenerator {
     const result: Seen = { schema: {}, count: 1, cycle: undefined };
     this.seen.set(schema, result);
 
-    // if(schema._zod.parent){
-    //   // schema was cloned from another schema
-    //   result.
-    // }
-
     if (schema._zod.toJSONSchema) {
       // custom method overrides default behavior
       result.schema = schema._zod.toJSONSchema() as any;
-      // return
     }
 
     // check if external
@@ -144,13 +124,6 @@ export class JSONSchemaGenerator {
     //   result.external = ext;
     // }
 
-    // // metadata
-    // const meta = this.metadataRegistry.get(schema);
-    // if (meta) {
-    //   Object.assign(_json, meta);
-    // }
-
-    // const def = (schema as schemas.$ZodTypes)._zod.def;
     const params = {
       ..._params,
       schemaPath: [..._params.schemaPath, schema],
@@ -159,7 +132,9 @@ export class JSONSchemaGenerator {
 
     if (schema._zod.parent) {
       // schema was cloned from another schema
-      result.schema._ref = this.process(schema._zod.parent, params);
+      result.ref = schema._zod.parent;
+      this.process(schema._zod.parent, params);
+      this.seen.get(schema._zod.parent)!.isParent = true;
     } else {
       const _json = result.schema;
       switch (def.type) {
@@ -234,7 +209,6 @@ export class JSONSchemaGenerator {
         }
         case "null": {
           _json.type = "null";
-          // const json = { type: "null" } as JSONSchema.NullSchema;
           break;
         }
         case "any": {
@@ -276,10 +250,7 @@ export class JSONSchemaGenerator {
           json.type = "object";
           json.properties = {};
           const shape = def.shape; // params.shapeCache.get(schema)!;
-          // if (!shape) {
-          //   shape = def.shape;
-          //   params.shapeCache.set(schema, shape);
-          // }
+
           for (const key in shape) {
             json.properties[key] = this.process(shape[key], {
               ...params,
@@ -455,8 +426,8 @@ export class JSONSchemaGenerator {
           break;
         }
         case "nonoptional": {
-          const inner = this.process(def.innerType, params);
-          Object.assign(_json, inner);
+          this.process(def.innerType, params);
+          result.ref = def.innerType;
           break;
         }
         case "success": {
@@ -465,21 +436,22 @@ export class JSONSchemaGenerator {
           break;
         }
         case "default": {
-          const inner = this.process(def.innerType, params);
-          Object.assign(_json, inner);
+          this.process(def.innerType, params);
+          result.ref = def.innerType;
           _json.default = def.defaultValue;
           break;
         }
         case "prefault": {
-          const inner = this.process(def.innerType, params);
-          Object.assign(_json, inner);
-          _json.default = schema["~standard"].validate(undefined);
+          this.process(def.innerType, params);
+          result.ref = def.innerType;
+          if (this.io === "input") _json._prefault = def.defaultValue;
+
           break;
         }
         case "catch": {
           // use conditionals
-          const inner = this.process(def.innerType, params);
-          Object.assign(_json, inner);
+          this.process(def.innerType, params);
+          result.ref = def.innerType;
           let catchValue: any;
           try {
             catchValue = def.catchValue(undefined as any);
@@ -495,23 +467,6 @@ export class JSONSchemaGenerator {
           }
           break;
         }
-        case "pipe": {
-          const innerType = this.io === "input" ? def.in : def.out;
-          const inner = this.process(innerType, params);
-          _json._ref = inner;
-
-          break;
-        }
-        case "readonly": {
-          _json._ref = this.process(def.innerType, params);
-          _json.readOnly = true;
-          // const inner = this.process(def.innerType, params);
-          // Object.assign(_json, inner);
-          // _json.allOf = [inner];
-          // result.extra.readOnly = true;
-          // _json.readOnly = true;
-          break;
-        }
         case "template_literal": {
           const json = _json as JSONSchema.StringSchema;
           const pattern = schema._zod.pattern;
@@ -520,23 +475,33 @@ export class JSONSchemaGenerator {
           json.pattern = pattern.source;
           break;
         }
-        case "promise": {
-          const inner = this.process(def.innerType, params);
-          // result.schema = inner;
-          _json._ref = inner;
+        case "pipe": {
+          const innerType = this.io === "input" ? def.in : def.out;
+          this.process(innerType, params);
+          result.ref = innerType;
+          break;
+        }
+        case "readonly": {
+          this.process(def.innerType, params);
+          result.ref = def.innerType;
+          _json.readOnly = true;
           break;
         }
         // passthrough types
+        case "promise": {
+          this.process(def.innerType, params);
+          result.ref = def.innerType;
+          break;
+        }
         case "optional": {
-          // result.schema = this.process(def.innerType, params);
-          _json._ref = this.process(def.innerType, params);
+          this.process(def.innerType, params);
+          result.ref = def.innerType;
           break;
         }
         case "lazy": {
           const innerType = (schema as schemas.$ZodLazy)._zod.innerType;
-          const inner = this.process(innerType, params);
-          // result.schema = inner;
-          _json._ref = inner;
+          this.process(innerType, params);
+          result.ref = innerType;
           break;
         }
         case "custom": {
@@ -553,19 +518,19 @@ export class JSONSchemaGenerator {
 
     // metadata
     const meta = this.metadataRegistry.get(schema);
-    if (meta) {
-      Object.assign(result.schema, meta);
+    if (meta) Object.assign(result.schema, meta);
+    if (this.io === "input" && def.type === "pipe") {
+      // examples/defaults only apply to output type of pipe
+      delete result.schema.examples;
+      delete result.schema.default;
+      if (result.schema._prefault) result.schema.default = result.schema._prefault;
     }
+    if (this.io === "input" && result.schema._prefault) result.schema.default ??= result.schema._prefault;
+    delete result.schema._prefault;
 
     // pulling fresh from this.seen in case it was overwritten
     const _result = this.seen.get(schema)!;
 
-    this.override({
-      zodSchema: schema,
-      jsonSchema: _result.schema,
-    });
-
-    // Object.assign(_result.cached, _result.schema);
     return _result.schema;
   }
 
@@ -578,9 +543,7 @@ export class JSONSchemaGenerator {
       external: _params?.external ?? undefined,
     } satisfies EmitParams;
 
-    // iterate over seen map
-    // const result: JSONSchema.BaseSchema = {};
-    // const defs: JSONSchema.BaseSchema["$defs"] = params.external?.defs ?? {};
+    // iterate over seen map;
     const root = this.seen.get(schema);
 
     if (!root) throw new Error("Unprocessed schema. This is a bug in Zod.");
@@ -620,17 +583,21 @@ export class JSONSchemaGenerator {
 
     const extractToDef = (entry: [schemas.$ZodType<unknown, unknown>, Seen]): void => {
       if (entry[1].schema.$ref) {
-        // throw new Error("Already extracted");
         return;
       }
       const seen = entry[1];
       const { ref, defId } = makeURI(entry);
-      // defId won't be set if the schema is a reference to an external schema
 
       seen.def = { ...seen.schema };
+      // defId won't be set if the schema is a reference to an external schema
       if (defId) seen.defId = defId;
       // wipe away all properties except $ref
-      schemaToRef(seen, ref);
+      const schema = seen.schema;
+      for (const key in schema) {
+        // @ts-ignore
+        delete schema[key];
+        schema.$ref = ref;
+      }
     };
 
     // extract schemas into $defs
@@ -686,13 +653,45 @@ export class JSONSchemaGenerator {
       }
     }
 
+    // flatten _refs
+    const flattenRef = (zodSchema: schemas.$ZodType, params: Pick<ToJSONSchemaParams, "target">) => {
+      const seen = this.seen.get(zodSchema)!;
+      const schema = seen.def ?? seen.schema;
+
+      const _schema = { ...schema };
+      if (seen.ref === null) {
+        return;
+      }
+
+      const ref = seen.ref;
+      seen.ref = null;
+      if (ref) {
+        flattenRef(ref, params);
+
+        const refSchema = this.seen.get(ref)!.schema;
+
+        if (refSchema.$ref && params.target === "draft-7") {
+          schema.allOf = schema.allOf ?? [];
+          schema.allOf.push(refSchema);
+        } else {
+          Object.assign(schema, refSchema);
+          Object.assign(schema, _schema); // this is to prevent overwriting any fields in the original schema
+        }
+      }
+
+      if (!seen.isParent)
+        this.override({
+          zodSchema,
+          jsonSchema: schema,
+        });
+    };
+
     for (const entry of this.seen.entries()) {
-      const seen = entry[1];
-      flattenRef(seen.schema, { target: this.target });
-      if (seen.def) flattenRef(seen.def, { target: this.target });
+      flattenRef(entry[0], { target: this.target });
     }
 
     const result = { ...root.def };
+
     const defs: JSONSchema.BaseSchema["$defs"] = params.external?.defs ?? {};
     for (const entry of this.seen.entries()) {
       const seen = entry[1];
@@ -711,7 +710,7 @@ export class JSONSchemaGenerator {
     }
 
     try {
-      // this essentially "finalizes" this schema
+      // this "finalizes" this schema and ensures all cycles are removed
       // each call to .emit() is functionally independent
       // though the seen map is shared
       return JSON.parse(JSON.stringify(result));
@@ -721,31 +720,6 @@ export class JSONSchemaGenerator {
   }
 }
 
-// flatten _refs
-const flattenRef = (schema: JSONSchema.BaseSchema, params: Pick<ToJSONSchemaParams, "target">) => {
-  const _schema = { ...schema };
-  if (schema._ref) flattenRef(schema._ref, params);
-  const ref = schema._ref;
-  if (ref) {
-    if (ref.$ref && params.target === "draft-7") {
-      schema.allOf = schema.allOf ?? [];
-      schema.allOf.push(ref);
-    } else {
-      Object.assign(schema, ref);
-      Object.assign(schema, _schema); // this is to prevent overwriting any fields in the original schema
-    }
-  }
-  delete schema._ref;
-};
-
-function schemaToRef(seen: Seen, ref: string) {
-  const schema = seen.schema;
-  for (const key in schema) {
-    delete schema[key];
-    schema.$ref = ref;
-  }
-}
-
 interface ToJSONSchemaParams extends Omit<JSONSchemaGeneratorParams & EmitParams, never> {}
 interface RegistryToJSONSchemaParams extends Omit<JSONSchemaGeneratorParams & EmitParams, never> {
   uri?: (id: string) => string;
diff --git a/packages/zod/src/v4/core/util.ts b/packages/zod/src/v4/core/util.ts
index 264d9d37..affb0cd1 100644
--- a/packages/zod/src/v4/core/util.ts
+++ b/packages/zod/src/v4/core/util.ts
@@ -321,7 +321,8 @@ export function isObject(data: any): data is Record<PropertyKey, unknown> {
 
 export const allowsEval: { value: boolean } = cached(() => {
   try {
-    new Function("");
+    const F = Function;
+    new F("");
     return true;
   } catch (_) {
     return false;
@@ -746,8 +747,8 @@ export function finalizeIssue(
   config: $ZodConfig
 ): errors.$ZodIssue {
   const full = { ...iss, path: iss.path ?? [] } as errors.$ZodIssue;
+
   // for backwards compatibility
-  // const _ctx: errors.$ZodErrorMapCtx = { data: iss.input, defaultError: undefined as any };
   if (!iss.message) {
     const message =
       unwrapMessage(iss.inst?._zod.def?.error?.(iss as never)) ??
@@ -764,6 +765,7 @@ export function finalizeIssue(
   if (!ctx?.reportInput) {
     delete (full as any).input;
   }
+
   return full;
 }
 
@@ -805,3 +807,8 @@ export function cleanEnum(obj: Record<string, EnumValue>): EnumValue[] {
     })
     .map((el) => el[1]);
 }
+
+// instanceof
+export abstract class Class {
+  constructor(..._args: any[]) {}
+}
diff --git a/packages/zod/src/v4/mini/schemas.ts b/packages/zod/src/v4/mini/schemas.ts
index 5cfa4805..ef86000d 100644
--- a/packages/zod/src/v4/mini/schemas.ts
+++ b/packages/zod/src/v4/mini/schemas.ts
@@ -694,10 +694,9 @@ export function keyof<T extends ZodMiniObject>(schema: T): ZodMiniLiteral<keyof
 export interface ZodMiniObject<
   // @ts-ignore Cast variance
   out Shape extends core.$ZodShape = core.$ZodShape,
-  OutExtra extends Record<string, unknown> = Record<string, unknown>,
-  InExtra extends Record<string, unknown> = Record<string, unknown>,
+  out Config extends core.$ZodObjectConfig = core.$ZodObjectConfig,
 > extends ZodMiniType {
-  _zod: core.$ZodObjectInternals<Shape, OutExtra, InExtra>;
+  _zod: core.$ZodObjectInternals<Shape, Config>;
   shape: Shape;
 }
 export const ZodMiniObject: core.$constructor<ZodMiniObject> = /*@__PURE__*/ core.$constructor(
@@ -710,7 +709,7 @@ export const ZodMiniObject: core.$constructor<ZodMiniObject> = /*@__PURE__*/ cor
 export function object<T extends core.$ZodLooseShape = Record<never, SomeType>>(
   shape?: T,
   params?: string | core.$ZodObjectParams
-): ZodMiniObject<T, {}, {}> {
+): ZodMiniObject<T, core.$strip> {
   const def: core.$ZodObjectDef = {
     type: "object",
     get shape() {
@@ -727,7 +726,7 @@ export function object<T extends core.$ZodLooseShape = Record<never, SomeType>>(
 export function strictObject<T extends core.$ZodLooseShape>(
   shape: T,
   params?: string | core.$ZodObjectParams
-): ZodMiniObject<T, {}, {}> {
+): ZodMiniObject<T, core.$strict> {
   return new ZodMiniObject({
     type: "object",
     // shape: shape as core.$ZodLooseShape,
@@ -748,7 +747,7 @@ export function strictObject<T extends core.$ZodLooseShape>(
 export function looseObject<T extends core.$ZodLooseShape>(
   shape: T,
   params?: string | core.$ZodObjectParams
-): ZodMiniObject<T, { [k: string]: unknown }, { [k: string]: unknown }> {
+): ZodMiniObject<T, core.$loose> {
   return new ZodMiniObject({
     type: "object",
     // shape: shape as core.$ZodLooseShape,
@@ -768,7 +767,7 @@ export function looseObject<T extends core.$ZodLooseShape>(
 export function extend<T extends ZodMiniObject, U extends core.$ZodLooseShape>(
   schema: T,
   shape: U
-): ZodMiniObject<util.Extend<T["shape"], U>, T["_zod"]["outextra"], T["_zod"]["inextra"]> {
+): ZodMiniObject<util.Extend<T["shape"], U>, T["_zod"]["config"]> {
   return util.extend(schema, shape);
 }
 
@@ -776,7 +775,7 @@ export function extend<T extends ZodMiniObject, U extends core.$ZodLooseShape>(
 export function merge<T extends ZodMiniObject, U extends ZodMiniObject>(
   a: T,
   b: U
-): ZodMiniObject<util.Extend<T["shape"], U["shape"]>, T["_zod"]["outextra"], T["_zod"]["inextra"]>;
+): ZodMiniObject<util.Extend<T["shape"], U["shape"]>, T["_zod"]["config"]>;
 export function merge(schema: ZodMiniObject, shape: any): ZodMiniObject {
   return util.extend(schema, shape);
 }
@@ -784,11 +783,7 @@ export function merge(schema: ZodMiniObject, shape: any): ZodMiniObject {
 export function pick<T extends ZodMiniObject, M extends util.Mask<keyof T["shape"]>>(
   schema: T,
   mask: M
-): ZodMiniObject<
-  util.Flatten<Pick<T["shape"], keyof T["shape"] & keyof M>>,
-  T["_zod"]["outextra"],
-  T["_zod"]["inextra"]
-> {
+): ZodMiniObject<util.Flatten<Pick<T["shape"], keyof T["shape"] & keyof M>>, T["_zod"]["config"]> {
   return util.pick(schema, mask as any);
 }
 
@@ -797,7 +792,7 @@ export function pick<T extends ZodMiniObject, M extends util.Mask<keyof T["shape
 export function omit<T extends ZodMiniObject, const M extends util.Mask<keyof T["shape"]>>(
   schema: T,
   mask: M
-): ZodMiniObject<util.Flatten<Omit<T["shape"], keyof M>>, T["_zod"]["outextra"], T["_zod"]["inextra"]> {
+): ZodMiniObject<util.Flatten<Omit<T["shape"], keyof M>>, T["_zod"]["config"]> {
   return util.omit(schema, mask);
 }
 
@@ -807,8 +802,7 @@ export function partial<T extends ZodMiniObject>(
   {
     [k in keyof T["shape"]]: ZodMiniOptional<T["shape"][k]>;
   },
-  T["_zod"]["outextra"],
-  T["_zod"]["inextra"]
+  T["_zod"]["config"]
 >;
 export function partial<T extends ZodMiniObject, M extends util.Mask<keyof T["shape"]>>(
   schema: T,
@@ -817,8 +811,7 @@ export function partial<T extends ZodMiniObject, M extends util.Mask<keyof T["sh
   {
     [k in keyof T["shape"]]: k extends keyof M ? ZodMiniOptional<T["shape"][k]> : T["shape"][k];
   },
-  T["_zod"]["outextra"],
-  T["_zod"]["inextra"]
+  T["_zod"]["config"]
 >;
 export function partial(schema: ZodMiniObject, mask?: object) {
   return util.partial(ZodMiniOptional, schema, mask);
@@ -841,8 +834,7 @@ export function required<T extends ZodMiniObject>(
   {
     [k in keyof T["shape"]]: ZodMiniNonOptional<T["shape"][k]>;
   },
-  T["_zod"]["outextra"],
-  T["_zod"]["inextra"]
+  T["_zod"]["config"]
 >;
 export function required<T extends ZodMiniObject, M extends util.Mask<keyof T["shape"]>>(
   schema: T,
@@ -854,8 +846,7 @@ export function required<T extends ZodMiniObject, M extends util.Mask<keyof T["s
       [k in keyof M & keyof T["shape"]]: ZodMiniNonOptional<T["shape"][k]>;
     }
   >,
-  T["_zod"]["outextra"],
-  T["_zod"]["inextra"]
+  T["_zod"]["config"]
 >;
 export function required(schema: ZodMiniObject, mask?: object) {
   return util.required(ZodMiniNonOptional, schema, mask);
@@ -1154,13 +1145,11 @@ export const ZodMiniTransform: core.$constructor<ZodMiniTransform> = /*@__PURE__
 );
 
 export function transform<I = unknown, O = I>(
-  fn: (input: I, ctx: core.ParsePayload) => O,
-  params?: string | core.$ZodTransformParams
+  fn: (input: I, ctx: core.ParsePayload) => O
 ): ZodMiniTransform<Awaited<O>, I> {
   return new ZodMiniTransform({
     type: "transform",
     transform: fn as any,
-    ...util.normalizeParams(params),
   }) as any;
 }
 
diff --git a/play.ts b/play.ts
index e31dc1a4..1263049d 100644
--- a/play.ts
+++ b/play.ts
@@ -1,11 +1,12 @@
 import { z } from "zod/v4";
 
-const baseCategorySchema = z.object({
-  name: z.string(),
-});
-type Category = z.infer<typeof baseCategorySchema> & {
-  subcategories: Category[];
-};
-const categorySchema: z.ZodType<Category> = baseCategorySchema.extend({
-  subcategories: z.lazy(() => categorySchema.array()),
-});
+z;
+
+const stringWithDefault = z
+  .pipe(
+    z.transform((v) => (v === "none" ? undefined : v)),
+    z.string()
+  )
+  .catch("default");
+
+stringWithDefault.parse(undefined);


Test patch:
diff --git a/packages/zod/src/v4/classic/tests/async-parsing.test.ts b/packages/zod/src/v4/classic/tests/async-parsing.test.ts
index dc2931ed..31097635 100644
--- a/packages/zod/src/v4/classic/tests/async-parsing.test.ts
+++ b/packages/zod/src/v4/classic/tests/async-parsing.test.ts
@@ -15,7 +15,7 @@ test("string async parse", async () => {
 
   const badResult = await stringSchema.safeParseAsync(badData);
   expect(badResult.success).toBe(false);
-  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z._ZodError);
+  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
 });
 
 /// number
@@ -30,7 +30,7 @@ test("number async parse", async () => {
 
   const badResult = await numberSchema.safeParseAsync(badData);
   expect(badResult.success).toBe(false);
-  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z._ZodError);
+  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
 });
 
 /// bigInt
@@ -45,7 +45,7 @@ test("bigInt async parse", async () => {
 
   const badResult = await bigIntSchema.safeParseAsync(badData);
   expect(badResult.success).toBe(false);
-  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z._ZodError);
+  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
 });
 
 /// boolean
@@ -60,7 +60,7 @@ test("boolean async parse", async () => {
 
   const badResult = await booleanSchema.safeParseAsync(badData);
   expect(badResult.success).toBe(false);
-  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z._ZodError);
+  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
 });
 
 /// date
@@ -75,7 +75,7 @@ test("date async parse", async () => {
 
   const badResult = await dateSchema.safeParseAsync(badData);
   expect(badResult.success).toBe(false);
-  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z._ZodError);
+  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
 });
 
 /// undefined
@@ -90,7 +90,7 @@ test("undefined async parse", async () => {
 
   const badResult = await undefinedSchema.safeParseAsync(badData);
   expect(badResult.success).toBe(false);
-  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z._ZodError);
+  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
 });
 
 /// null
@@ -105,7 +105,7 @@ test("null async parse", async () => {
 
   const badResult = await nullSchema.safeParseAsync(badData);
   expect(badResult.success).toBe(false);
-  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z._ZodError);
+  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
 });
 
 /// any
@@ -120,7 +120,7 @@ test("any async parse", async () => {
 
   // const badResult = await anySchema.safeParseAsync(badData);
   // expect(badResult.success).toBe(false);
-  // if (!badResult.success) expect(badResult.error).toBeInstanceOf(z._ZodError);
+  // if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
 });
 
 /// unknown
@@ -135,7 +135,7 @@ test("unknown async parse", async () => {
 
   // const badResult = await unknownSchema.safeParseAsync(badData);
   // expect(badResult.success).toBe(false);
-  // if (!badResult.success) expect(badResult.error).toBeInstanceOf(z._ZodError);
+  // if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
 });
 
 /// void
@@ -150,7 +150,7 @@ test("void async parse", async () => {
 
   const badResult = await voidSchema.safeParseAsync(badData);
   expect(badResult.success).toBe(false);
-  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z._ZodError);
+  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
 });
 
 /// array
@@ -165,7 +165,7 @@ test("array async parse", async () => {
 
   const badResult = await arraySchema.safeParseAsync(badData);
   expect(badResult.success).toBe(false);
-  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z._ZodError);
+  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
 });
 
 /// object
@@ -180,7 +180,7 @@ test("object async parse", async () => {
 
   const badResult = await objectSchema.safeParseAsync(badData);
   expect(badResult.success).toBe(false);
-  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z._ZodError);
+  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
 });
 
 /// union
@@ -195,7 +195,7 @@ test("union async parse", async () => {
 
   const badResult = await unionSchema.safeParseAsync(badData);
   expect(badResult.success).toBe(false);
-  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z._ZodError);
+  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
 });
 
 /// record
@@ -210,7 +210,7 @@ test("record async parse", async () => {
 
   const badResult = await recordSchema.safeParseAsync(badData);
   expect(badResult.success).toBe(false);
-  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z._ZodError);
+  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
 });
 
 /// function
@@ -225,7 +225,7 @@ test("record async parse", async () => {
 
 //   const badResult = await functionSchema.safeParseAsync(badData);
 //   expect(badResult.success).toBe(false);
-//   if (!badResult.success) expect(badResult.error).toBeInstanceOf(z._ZodError);
+//   if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
 // });
 
 /// literal
@@ -240,7 +240,7 @@ test("literal async parse", async () => {
 
   const badResult = await literalSchema.safeParseAsync(badData);
   expect(badResult.success).toBe(false);
-  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z._ZodError);
+  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
 });
 
 /// enum
@@ -255,7 +255,7 @@ test("enum async parse", async () => {
 
   const badResult = await enumSchema.safeParseAsync(badData);
   expect(badResult.success).toBe(false);
-  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z._ZodError);
+  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
 });
 
 /// nativeEnum
@@ -274,7 +274,7 @@ test("nativeEnum async parse", async () => {
 
   const badResult = await nativeEnumSchema.safeParseAsync(badData);
   expect(badResult.success).toBe(false);
-  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z._ZodError);
+  if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
 });
 
 /// promise
@@ -292,7 +292,7 @@ test("promise async parse bad", async () => {
   const badData = Promise.resolve("XXX");
   const badResult = await promiseSchema.safeParseAsync(badData);
   expect(badResult.success).toBe(false);
-  expect(badResult.error).toBeInstanceOf(z._ZodError);
+  expect(badResult.error).toBeInstanceOf(z.ZodError);
 });
 
 test("async validation non-empty strings", async () => {
diff --git a/packages/zod/src/v4/classic/tests/discriminated-unions.test.ts b/packages/zod/src/v4/classic/tests/discriminated-unions.test.ts
index d0957376..de777f5b 100644
--- a/packages/zod/src/v4/classic/tests/discriminated-unions.test.ts
+++ b/packages/zod/src/v4/classic/tests/discriminated-unions.test.ts
@@ -105,7 +105,7 @@ test("valid - discriminator value of various primitive types", () => {
     type: "not_a_key",
     val: "val",
   });
-  expect(fail.error).toBeInstanceOf(z._ZodError);
+  expect(fail.error).toBeInstanceOf(z.ZodError);
 });
 
 test("invalid - null", () => {
@@ -156,7 +156,9 @@ test("invalid discriminator value", () => {
             "errors": [],
             "message": "Invalid input",
             "note": "No matching discriminator",
-            "path": [],
+            "path": [
+              "type",
+            ],
           },
         ],
       },
diff --git a/packages/zod/src/v4/classic/tests/error-utils.test.ts b/packages/zod/src/v4/classic/tests/error-utils.test.ts
index c023afc0..d5f4bb29 100644
--- a/packages/zod/src/v4/classic/tests/error-utils.test.ts
+++ b/packages/zod/src/v4/classic/tests/error-utils.test.ts
@@ -374,6 +374,48 @@ test("z.treeifyError", () => {
   `);
 });
 
+test("z.treeifyError 2", () => {
+  const schema = z.strictObject({
+    name: z.string(),
+    logLevel: z.union([z.string(), z.number()]),
+    env: z.literal(["production", "development"]),
+  });
+
+  const data = {
+    name: 1000,
+    logLevel: false,
+    extra: 1000,
+  };
+
+  const result = schema.safeParse(data);
+  const err = z.treeifyError(result.error!);
+  expect(err).toMatchInlineSnapshot(`
+    {
+      "errors": [
+        "Unrecognized key: "extra"",
+      ],
+      "properties": {
+        "env": {
+          "errors": [
+            "Invalid option: expected one of "production"|"development"",
+          ],
+        },
+        "logLevel": {
+          "errors": [
+            "Invalid input: expected string, received boolean",
+            "Invalid input: expected number, received boolean",
+          ],
+        },
+        "name": {
+          "errors": [
+            "Invalid input: expected string, received number",
+          ],
+        },
+      },
+    }
+  `);
+});
+
 test("z.prettifyError", () => {
   expect(z.prettifyError(result.error!)).toMatchInlineSnapshot(`
     "✖ Unrecognized key: "extra"
@@ -419,10 +461,12 @@ test("z.toDotPath", () => {
 
 test("inheritance", () => {
   const e1 = new z.ZodError([]);
-  const e2 = new z._ZodError([]);
-
+  expect(e1).toBeInstanceOf(z.core.$ZodError);
   expect(e1).toBeInstanceOf(z.ZodError);
-  expect(e2).toBeInstanceOf(z._ZodError);
-  expect(e2).not.toBeInstanceOf(z.ZodError);
-  expect(e1).toBeInstanceOf(z._ZodError);
+  expect(e1).not.toBeInstanceOf(Error);
+
+  const e2 = new z.ZodRealError([]);
+  expect(e2).toBeInstanceOf(z.ZodError);
+  expect(e2).toBeInstanceOf(z.ZodRealError);
+  expect(e2).toBeInstanceOf(Error);
 });
diff --git a/packages/zod/src/v4/classic/tests/error.test.ts b/packages/zod/src/v4/classic/tests/error.test.ts
index 711c1083..7071e3ec 100644
--- a/packages/zod/src/v4/classic/tests/error.test.ts
+++ b/packages/zod/src/v4/classic/tests/error.test.ts
@@ -683,3 +683,29 @@ test("string error params", () => {
   const j = z.array(z.string(), "Bad array!");
   expect(j.safeParse(null).error!.issues[0].message).toBe("Bad array!");
 });
+
+test("error inheritance", () => {
+  const e1 = z.string().safeParse(123).error!;
+  expect(e1).toBeInstanceOf(z.core.$ZodError);
+  expect(e1).toBeInstanceOf(z.ZodError);
+  expect(e1).toBeInstanceOf(z.ZodRealError);
+  expect(e1).not.toBeInstanceOf(Error);
+
+  try {
+    z.string().parse(123);
+  } catch (e2) {
+    expect(e1).toBeInstanceOf(z.core.$ZodError);
+    expect(e2).toBeInstanceOf(z.ZodError);
+    expect(e2).toBeInstanceOf(z.ZodRealError);
+    expect(e2).toBeInstanceOf(Error);
+  }
+});
+
+test("error serialization", () => {
+  try {
+    z.string().parse(123);
+  } catch (e) {
+    console.dir(e, { depth: null });
+    expect(e).toMatchInlineSnapshot(`[Error]`);
+  }
+});
diff --git a/packages/zod/src/v4/classic/tests/intersection.test.ts b/packages/zod/src/v4/classic/tests/intersection.test.ts
index 76d045f1..d1538c03 100644
--- a/packages/zod/src/v4/classic/tests/intersection.test.ts
+++ b/packages/zod/src/v4/classic/tests/intersection.test.ts
@@ -21,7 +21,7 @@ test("object intersection: loose", () => {
 
   const C = z.intersection(A, B); // BaseC.merge(HasID);
   type C = z.infer<typeof C>;
-  expectTypeOf<C>().toEqualTypeOf<{ a: string } & { b: string } & Record<string, unknown>>();
+  expectTypeOf<C>().toEqualTypeOf<{ a: string; [x: string]: unknown } & { b: string }>();
   const data = { a: "foo", b: "foo", c: "extra" };
   expect(C.parse(data)).toEqual(data);
   expect(() => C.parse({ a: "foo" })).toThrow();
diff --git a/packages/zod/src/v4/classic/tests/json-schema.test.ts b/packages/zod/src/v4/classic/tests/json-schema.test.ts
index df6ad2ea..9786d948 100644
--- a/packages/zod/src/v4/classic/tests/json-schema.test.ts
+++ b/packages/zod/src/v4/classic/tests/json-schema.test.ts
@@ -109,7 +109,7 @@ describe("toJSONSchema", () => {
       {
         "contentEncoding": "base64",
         "format": "base64",
-        "pattern": "^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$",
+        "pattern": "^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$",
         "type": "string",
       }
     `);
@@ -293,7 +293,7 @@ describe("toJSONSchema", () => {
       {
         "contentEncoding": "base64",
         "format": "base64",
-        "pattern": "^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$",
+        "pattern": "^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$",
         "type": "string",
       }
     `);
@@ -851,6 +851,27 @@ test("override", () => {
   `);
 });
 
+test("override: do not run on references", () => {
+  let overrideCount = 0;
+  const schema = z
+    .union([z.string().date(), z.string().datetime(), z.string().datetime({ local: true })])
+    .meta({ a: true })
+    .transform((str) => new Date(str))
+    .meta({ b: true })
+    .pipe(z.date())
+    .meta({ c: true })
+    .brand("dateIn");
+  z.toJSONSchema(schema, {
+    unrepresentable: "any",
+    io: "input",
+    override(_) {
+      overrideCount++;
+    },
+  });
+
+  expect(overrideCount).toBe(6);
+});
+
 test("pipe", () => {
   const mySchema = z
     .string()
@@ -1352,6 +1373,53 @@ test("_ref", () => {
   `);
 });
 
+test("defaults/prefaults", () => {
+  const a = z
+    .string()
+    .transform((val) => val.length)
+    .pipe(z.number());
+  const b = a.prefault("hello");
+  const c = a.default(1234);
+
+  // a
+  expect(toJSONSchema(a)).toMatchInlineSnapshot(`
+    {
+      "type": "number",
+    }
+  `);
+  expect(toJSONSchema(a, { io: "input" })).toMatchInlineSnapshot(`
+    {
+      "type": "string",
+    }
+  `);
+
+  // b
+  expect(toJSONSchema(b)).toMatchInlineSnapshot(`
+    {
+      "type": "number",
+    }
+  `);
+  expect(toJSONSchema(b, { io: "input" })).toMatchInlineSnapshot(`
+    {
+      "default": "hello",
+      "type": "string",
+    }
+  `);
+  // c
+  expect(toJSONSchema(c)).toMatchInlineSnapshot(`
+    {
+      "default": 1234,
+      "type": "number",
+    }
+  `);
+  expect(toJSONSchema(c, { io: "input" })).toMatchInlineSnapshot(`
+    {
+      "default": 1234,
+      "type": "string",
+    }
+  `);
+});
+
 test("input type", () => {
   const schema = z.object({
     a: z.string(),
@@ -1384,9 +1452,7 @@ test("input type", () => {
           ],
         },
         "e": {
-          "default": {
-            "value": "hello",
-          },
+          "default": "hello",
           "type": "string",
         },
       },
@@ -1421,9 +1487,6 @@ test("input type", () => {
           ],
         },
         "e": {
-          "default": {
-            "value": "hello",
-          },
           "type": "string",
         },
       },
@@ -1437,3 +1500,47 @@ test("input type", () => {
     }
   `);
 });
+
+test("examples on pipe", () => {
+  const schema = z
+    .string()
+    .meta({ examples: ["test"] })
+    .transform(Number)
+    // .pipe(z.transform(Number).meta({ examples: [4] }))
+    .meta({ examples: [4] });
+
+  const i = z.toJSONSchema(schema, { io: "input", unrepresentable: "any" });
+  expect(i).toMatchInlineSnapshot(`
+    {
+      "examples": [
+        "test",
+      ],
+      "type": "string",
+    }
+  `);
+  const o = z.toJSONSchema(schema, { io: "output", unrepresentable: "any" });
+  expect(o).toMatchInlineSnapshot(`
+    {
+      "examples": [
+        4,
+      ],
+    }
+  `);
+});
+
+test("override with refs", () => {
+  const a = z.string().optional();
+  const result = z.toJSONSchema(a, {
+    override(ctx) {
+      if (ctx.zodSchema._zod.def.type === "string") {
+        ctx.jsonSchema.type = "STRING";
+      }
+    },
+  });
+
+  expect(result).toMatchInlineSnapshot(`
+    {
+      "type": "STRING",
+    }
+  `);
+});
diff --git a/packages/zod/src/v4/classic/tests/object.test.ts b/packages/zod/src/v4/classic/tests/object.test.ts
index 3c58c6b6..0429eade 100644
--- a/packages/zod/src/v4/classic/tests/object.test.ts
+++ b/packages/zod/src/v4/classic/tests/object.test.ts
@@ -417,7 +417,7 @@ test("passthrough index signature", () => {
   expectTypeOf<a>().toEqualTypeOf<{ a: string }>();
   const b = a.passthrough();
   type b = z.infer<typeof b>;
-  expectTypeOf<b>().toEqualTypeOf<{ a: string } & { [k: string]: unknown }>();
+  expectTypeOf<b>().toEqualTypeOf<{ a: string; [k: string]: unknown }>();
 });
 
 // test("xor", () => {
@@ -454,3 +454,23 @@ test("null prototype", () => {
   obj.a = "foo";
   expect(schema.parse(obj)).toEqual({ a: "foo" });
 });
+
+test("empty objects", () => {
+  const A = z.looseObject({});
+  type Ain = z.input<typeof A>;
+  expectTypeOf<Ain>().toEqualTypeOf<Record<string, unknown>>();
+  type Aout = z.output<typeof A>;
+  expectTypeOf<Aout>().toEqualTypeOf<Record<string, unknown>>();
+
+  const B = z.object({});
+  type Bout = z.output<typeof B>;
+  expectTypeOf<Bout>().toEqualTypeOf<Record<string, never>>();
+  type Bin = z.input<typeof B>;
+  expectTypeOf<Bin>().toEqualTypeOf<Record<string, never>>();
+
+  const C = z.strictObject({});
+  type Cout = z.output<typeof C>;
+  expectTypeOf<Cout>().toEqualTypeOf<Record<string, never>>();
+  type Cin = z.input<typeof C>;
+  expectTypeOf<Cin>().toEqualTypeOf<Record<string, never>>();
+});
diff --git a/packages/zod/src/v4/classic/tests/pickomit-object.test.ts b/packages/zod/src/v4/classic/tests/pickomit.test.ts
similarity index 98%
rename from packages/zod/src/v4/classic/tests/pickomit-object.test.ts
rename to packages/zod/src/v4/classic/tests/pickomit.test.ts
index 30a0d83b..5e8819c8 100644
--- a/packages/zod/src/v4/classic/tests/pickomit-object.test.ts
+++ b/packages/zod/src/v4/classic/tests/pickomit.test.ts
@@ -93,7 +93,7 @@ test("omit - remove optional", () => {
 test("nonstrict inference", () => {
   const laxfish = fish.pick({ name: true }).catchall(z.any());
   type laxfish = z.infer<typeof laxfish>;
-  expectTypeOf<laxfish>().toEqualTypeOf<{ name: string } & { [k: string]: any }>();
+  expectTypeOf<laxfish>().toEqualTypeOf<{ name: string; [k: string]: any }>();
 });
 
 test("nonstrict parsing - pass", () => {
diff --git a/packages/zod/src/v4/classic/tests/pipe.test.ts b/packages/zod/src/v4/classic/tests/pipe.test.ts
index 23559ab6..0a338215 100644
--- a/packages/zod/src/v4/classic/tests/pipe.test.ts
+++ b/packages/zod/src/v4/classic/tests/pipe.test.ts
@@ -15,6 +15,20 @@ test("string to number pipe async", async () => {
   expect(await schema.parseAsync("1234")).toEqual(1234);
 });
 
+test("string with default fallback", () => {
+  const stringWithDefault = z
+    .pipe(
+      z.transform((v) => (v === "none" ? undefined : v)),
+      z.string()
+    )
+    .catch("default");
+
+  expect(stringWithDefault.parse("ok")).toBe("ok");
+  expect(stringWithDefault.parse(undefined)).toBe("default");
+  expect(stringWithDefault.parse("none")).toBe("default");
+  expect(stringWithDefault.parse(15)).toBe("default");
+});
+
 test("continue on non-fatal errors", () => {
   const schema = z
     .string()
diff --git a/packages/zod/src/v4/classic/tests/promise.test.ts b/packages/zod/src/v4/classic/tests/promise.test.ts
index e3919782..b857a2b6 100644
--- a/packages/zod/src/v4/classic/tests/promise.test.ts
+++ b/packages/zod/src/v4/classic/tests/promise.test.ts
@@ -29,13 +29,13 @@ test("promise parsing success", async () => {
 test("promise parsing fail", async () => {
   const bad = await promSchema.safeParseAsync(Promise.resolve({ name: "Bobby", age: "10" }));
   expect(bad.success).toBe(false);
-  expect(bad.error).toBeInstanceOf(z._ZodError);
+  expect(bad.error).toBeInstanceOf(z.ZodError);
 });
 
 test("promise parsing fail 2", async () => {
   const result = await promSchema.safeParseAsync(Promise.resolve({ name: "Bobby", age: "10" }));
   expect(result.success).toBe(false);
-  expect(result.error).toBeInstanceOf(z._ZodError);
+  expect(result.error).toBeInstanceOf(z.ZodError);
 });
 
 test("promise parsing fail", () => {
diff --git a/packages/zod/src/v4/classic/tests/string.test.ts b/packages/zod/src/v4/classic/tests/string.test.ts
index 1facb0d6..9d7fb775 100644
--- a/packages/zod/src/v4/classic/tests/string.test.ts
+++ b/packages/zod/src/v4/classic/tests/string.test.ts
@@ -1,3 +1,4 @@
+import { randomBytes } from "node:crypto";
 import { expect, test } from "vitest";
 
 import * as z from "zod/v4";
@@ -207,22 +208,22 @@ test("base64url validations", () => {
 
   const validBase64URLStrings = [
     "SGVsbG8gV29ybGQ", // "Hello World"
-    "SGVsbG8gV29ybGQ=", // "Hello World" with padding
+
     "VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw", // "This is an encoded string"
-    "VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw==", // "This is an encoded string" with padding
+
     "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcms", // "Many hands make light work"
-    "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcms=", // "Many hands make light work" with padding
+
     "UGF0aWVuY2UgaXMgdGhlIGtleSB0byBzdWNjZXNz", // "Patience is the key to success"
     "QmFzZTY0IGVuY29kaW5nIGlzIGZ1bg", // "Base64 encoding is fun"
-    "QmFzZTY0IGVuY29kaW5nIGlzIGZ1bg==", // "Base64 encoding is fun" with padding
+
     "MTIzNDU2Nzg5MA", // "1234567890"
-    "MTIzNDU2Nzg5MA==", // "1234567890" with padding
+
     "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo", // "abcdefghijklmnopqrstuvwxyz"
-    "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=", // "abcdefghijklmnopqrstuvwxyz with padding"
+
     "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo", // "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-    "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=", // "ABCDEFGHIJKLMNOPQRSTUVWXYZ" with padding
+
     "ISIkJSMmJyonKCk", // "!\"#$%&'()*"
-    "ISIkJSMmJyonKCk=", // "!\"#$%&'()*" with padding
+
     "", // Empty string is technically valid base64url
     "w7_Dv8O-w74K", // ÿÿþþ
     "123456",
@@ -239,6 +240,16 @@ test("base64url validations", () => {
     "!UGF0aWVuY2UgaXMgdGhlIGtleSB0byBzdWNjZXNz", // Invalid character '!'
     "?QmFzZTY0IGVuY29kaW5nIGlzIGZ1bg==", // Invalid character '?'
     ".MTIzND2Nzg5MC4=", // Invalid character '.'
+
+    // disallow valid padding
+    "SGVsbG8gV29ybGQ=", // "Hello World" with padding
+    "VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw==", // "This is an encoded string" with padding
+    "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcms=", // "Many hands make light work" with padding
+    "QmFzZTY0IGVuY29kaW5nIGlzIGZ1bg==", // "Base64 encoding is fun" with padding
+    "MTIzNDU2Nzg5MA==", // "1234567890" with padding
+    "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=", // "abcdefghijklmnopqrstuvwxyz with padding"
+    "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=", // "ABCDEFGHIJKLMNOPQRSTUVWXYZ" with padding
+    "ISIkJSMmJyonKCk=", // "!\"#$%&'()*" with padding
   ];
 
   for (const str of invalidBase64URLStrings) {
@@ -246,6 +257,13 @@ test("base64url validations", () => {
   }
 });
 
+test("big base64 and base64url", () => {
+  const bigbase64 = randomBytes(1024 * 1024 * 10).toString("base64");
+  z.base64().parse(bigbase64);
+  const bigbase64url = randomBytes(1024 * 1024 * 10).toString("base64url");
+  z.base64url().parse(bigbase64url);
+});
+
 test("jwt token", () => {
   const ONE_PART = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
   const NOT_BASE64 =
diff --git a/packages/zod/src/v4/mini/tests/error.test.ts b/packages/zod/src/v4/mini/tests/error.test.ts
index f4a5593e..d6267b73 100644
--- a/packages/zod/src/v4/mini/tests/error.test.ts
+++ b/packages/zod/src/v4/mini/tests/error.test.ts
@@ -7,3 +7,16 @@ test("no locale by default", () => {
   expect(result.error!.issues.length).toEqual(1);
   expect(result.error!.issues[0].message).toEqual("Invalid input");
 });
+
+test("error inheritance", () => {
+  const e1 = z.string().safeParse(123).error!;
+  expect(e1).toBeInstanceOf(z.core.$ZodError);
+  expect(e1).not.toBeInstanceOf(Error);
+
+  try {
+    z.string().parse(123);
+  } catch (e2) {
+    expect(e2).toBeInstanceOf(z.core.$ZodRealError);
+    expect(e2).toBeInstanceOf(Error);
+  }
+});