zod
semver
>=3.0.0postconditions11functions6last verified2026-04-17coverage score75%Postconditions — what we check
- parse · parse-validation-errorerrorWhenWhen input data does not match the schema definitionThrows
ZodErrorRequired handlingCaller MUST wrap parse() in try-catch block or use safeParse() instead. ZodError contains detailed validation failure information in the 'issues' array.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - parse · parse-type-coercion-errorerrorWhenWhen type coercion fails (e.g., z.coerce.date() receives invalid date string)Throws
ZodErrorRequired handlingCaller MUST handle coercion failures. Use safeParse() or try-catch.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - parse · parse-async-schema-errorerrorWhenschema.parse() is called on a schema that contains async refinements (.refine(async fn)) or async transforms (.transform(async fn)). The synchronous parse() path detects a pending Promise and throws immediately instead of returning the result.Throws
$ZodAsyncError: Encountered Promise during synchronous parse. Use .parseAsync() instead.Required handlingSchemas with async refinements/transforms MUST use parseAsync() or safeParseAsync(). If you have a schema that sometimes has async validators, always use the async variant: // ❌ WRONG const result = schema.parse(data); // ✅ CORRECT const result = await schema.parseAsync(data); Catch blocks checking `instanceof z.ZodError` will NOT catch this error — it is a plain Error, not a ZodError. Add a separate check or catch all.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - parseAsync · parse-async-validation-errorerrorWhenWhen input data does not match the schema definition or async refinements failThrows
ZodErrorRequired handlingCaller MUST wrap parseAsync() in try-catch block or use safeParseAsync() instead. Handle rejected promises appropriately.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - parseAsync · parse-async-refinement-errorerrorWhenWhen custom async refinement validation failsThrows
ZodErrorRequired handlingCaller MUST handle async refinement failures. The error.issues array will contain details about which refinements failed.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[5] - safeParse · safe-parse-success-checkwarningWhenWhen validation completes (success or failure)Throws
neverRequired handlingCaller MUST check result.success before accessing result.data or result.error. TypeScript discriminated unions enforce this at compile time.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[6] - safeParseAsync · safe-parse-async-success-checkwarningWhenWhen async validation completes (success or failure)Throws
neverRequired handlingCaller MUST check result.success before accessing result.data or result.error. Handle the promise appropriately.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[6] - encodeAsync · encode-async-unidirectional-transformerrorWhenschema.encodeAsync() is called on a schema containing a .transform() that has no inverse encode function. Zod v4 transforms created with .transform(fn) are unidirectional — they can decode (forward) but cannot encode (backward). Only schemas built with z.transform({ decode, encode }) bidirectional codecs support the encode direction.Throws
ZodEncodeError: Encountered unidirectional transform during encode: ZodTransformRequired handlingOnly use encodeAsync() on schemas built with bidirectional codecs: // ❌ WRONG — .transform() is unidirectional const schema = z.string().transform(s => s.toUpperCase()); await schema.encodeAsync('HELLO'); // throws ZodEncodeError // ✅ CORRECT — z.transform with encode/decode pair const schema = z.transform({ decode: (s: string) => s.toUpperCase(), encode: (s: string) => s.toLowerCase(), }); await schema.encodeAsync('HELLO'); // works Catch blocks MUST handle ZodEncodeError separately from ZodError: try { await schema.encodeAsync(value); } catch (error) { if (error instanceof ZodEncodeError) { /* schema bug */ } if (error instanceof z.ZodError) { /* validation failure */ } }costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - encodeAsync · encode-async-validation-errorerrorWhenschema.encodeAsync() is called with a value that fails the schema's output-side validation. The backward direction still runs validators — if the encoded value does not satisfy the schema, ZodError is thrown.Throws
ZodError with .issues array containing validation failuresRequired handlingCaller MUST catch both ZodEncodeError and ZodError: try { const encoded = await schema.encodeAsync(value); } catch (error) { if (error.name === 'ZodEncodeError') { // Schema design error — transform is not reversible throw new Error('Schema does not support encoding'); } if (error instanceof z.ZodError) { // Value failed validation during encode console.error(error.issues); } }costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - decodeAsync · decode-async-validation-errorerrorWhenschema.decodeAsync() is called with a value that fails the schema's type validation, constraints (min, max, regex, etc.), or synchronous refinements. The async parse path runs all validators and collects issues, then throws ZodError if any issues exist.Throws
ZodError with .issues array describing all validation failuresRequired handlingCaller MUST wrap decodeAsync() in try-catch: try { const result = await schema.decodeAsync(data); // Use result } catch (error) { if (error instanceof z.ZodError) { // Validation failed — inspect error.issues for (const issue of error.issues) { console.error(issue.path, issue.message); } } } Or use safeDecodeAsync() to get a non-throwing result object.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - decodeAsync · decode-async-refinement-errorerrorWhenschema.decodeAsync() is called on a schema with async refinements (.refine(async fn)) where the refinement rejects or returns false. The rejection is collected as a ZodIssue with code: 'custom' and thrown as a ZodError. Unhandled promise rejections inside async refinements crash the await if not caught by Zod.Throws
ZodError with issue code: 'custom' from the failed async refinementRequired handlingWhen async refinements call external services (DB uniqueness checks, API calls), handle both the ZodError AND consider that the underlying async error has been absorbed: try { const result = await schema.decodeAsync(data); } catch (error) { if (error instanceof z.ZodError) { const customIssues = error.issues.filter(i => i.code === 'custom'); // customIssues may reflect DB errors, not just validation failures throw new ValidationError(customIssues); } }costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
Sources
Every postcondition cites at least one of these. Numbered to match the footnotes above.
- [1]github.com/colinhacks/zodhttps://github.com/colinhacks/zod#parse
- [2]github.com/colinhacks/zodhttps://github.com/colinhacks/zod#coercion-for-primitives
- [3]raw.githubusercontent.com/colinhacks/zodhttps://raw.githubusercontent.com/colinhacks/zod/main/packages/zod/src/v4/core/parse.ts
- [4]zod.dev/apihttps://zod.dev/api?id=async-refinements
- [5]github.com/colinhacks/zodhttps://github.com/colinhacks/zod#refine
- [6]github.com/colinhacks/zodhttps://github.com/colinhacks/zod#safeparse
- [7]raw.githubusercontent.com/colinhacks/zodhttps://raw.githubusercontent.com/colinhacks/zod/main/packages/zod/src/v4/core/schemas.ts
- [8]zod.dev/apihttps://zod.dev/api
Need a different package?
Request a profile