This page documents Zod's mechanisms for providing fallback values when inputs are undefined. Zod provides two related but distinct features: defaults (applied after validation) and prefaults (applied before validation). Understanding when each executes in the validation pipeline is critical for correct usage, especially in bidirectional scenarios.
Zod provides two methods for supplying fallback values:
| Feature | Application Point | Direction Aware | Input Type | Output Type |
|---|---|---|---|---|
.default() | After validation | No | Input | undefined | Output (never undefined) |
.prefault() | Before validation | Yes | Input | undefined | Output (never undefined) |
Default values are applied after the underlying schema validates. If the input is undefined, the default value is used instead, and no validation occurs on the fallback.
Prefault values are applied before validation runs. The prefault value itself passes through the schema's validation pipeline, including all checks and transformations.
Sources: packages/zod/src/v4/classic/tests/default.test.ts4-6 packages/zod/src/v4/classic/tests/prefault.test.ts4-14 packages/zod/src/v4/core/util.ts180-186
The sequence of execution determines whether a fallback value is subjected to the schema's internal checks (like .trim() or .min()).
Diagram: Prefault vs Default in Validation Pipeline
Sources: packages/zod/src/v4/classic/tests/prefault.test.ts51-74 packages/zod/src/v4/classic/tests/default.test.ts116-235
The .default() method provides a fallback value when input is undefined. The default value is applied after validation completes.
Sources: packages/zod/src/v4/classic/tests/default.test.ts4-6
Applying .default() wraps the schema in a $ZodDefault type (exposed as ZodDefault in the classic API). The wrapped schema is accessible via .unwrap():
Sources: packages/zod/src/v4/classic/tests/default.test.ts19-23 packages/docs/content/packages/core.mdx80
When .default() is applied to a schema with transformations, the default value is applied to the output type after transformations have run:
Sources: packages/zod/src/v4/classic/tests/default.test.ts14-29
The .prefault() method provides a fallback value applied before validation runs. The prefault value itself is validated by the underlying schema:
Sources: packages/zod/src/v4/classic/tests/prefault.test.ts4-14
Prefault exists to handle cases where the default value should undergo validation and transformation. Consider a schema with .trim():
Sources: packages/zod/src/v4/classic/tests/prefault.test.ts4-14
Applying .prefault() wraps the schema in a $ZodPrefault type:
Sources: packages/zod/src/v4/classic/tests/prefault.test.ts6 packages/docs/content/packages/core.mdx152
Prefault values are direction-aware. They only apply when parsing in the forward direction (.parse(), .decode()). During backward direction operations (.encode()), prefaults are not applied. This prevents encoding from accidentally introducing fallback values into a data stream.
Diagram: Direction-Aware Prefault Behavior
Sources: packages/zod/src/v4/classic/tests/prefault.test.ts51-74
Both .default() and .prefault() transform the input type to make the schema effectively non-optional in the output.
Diagram: Type Transformation with Default/Prefault
Sources: packages/zod/src/v4/classic/tests/default.test.ts25-28 packages/zod/src/v4/classic/tests/prefault.test.ts10-13
The order of application determines whether the output can still be undefined.
Sources: packages/zod/src/v4/classic/tests/default.test.ts8-12
Sources: packages/zod/src/v4/classic/tests/default.test.ts44-53
When used in object schemas, properties with .default() or .prefault() become optional in the input type but required in the output type.
Sources: packages/zod/src/v4/classic/tests/prefault.test.ts16-37 packages/zod/src/v4/classic/tests/default.test.ts103-114
When a default value is an object, Zod creates a shallow clone on each parse to prevent mutations from leaking across parse calls.
Sources: packages/zod/src/v4/classic/tests/prefault.test.ts39-49
| Concept | Core Entity | Location |
|---|---|---|
| Default Schema | $ZodDefault | packages/docs/content/packages/core.mdx80 |
| Prefault Schema | $ZodPrefault | packages/docs/content/packages/core.mdx152 |
| Type check logic | _zod.run() | packages/docs/content/packages/core.mdx179 |
| Result Wrapper | SafeParseResult | packages/zod/src/v4/core/util.ts180 |
Sources: packages/docs/content/packages/core.mdx168-182 packages/zod/src/v4/core/util.ts180-186
Refresh this wiki
This wiki was recently refreshed. Please wait 2 days to refresh again.