---
library: zod
library-latest: "4.5.2"
library-latest-verified: 2026-08-29
model: claude-sonnet-5 (spawned via Agent model alias "sonnet")
model-self-reported-cutoff: "unknown to the model; it guessed 'first half of 2025' and declined to commit"
model-believed-latest: "Zod 4, 'GA sometime in 2025' — no minor/patch knowledge; low stated confidence"
test-date: 2026-08-29
battery: zod/v1 (6 idiomatic tasks + 3 direct questions)
tool-uses-during-test: 0
verified-against: https://zod.dev/v4/changelog · https://registry.npmjs.org/zod/latest
status: open (no retest yet)
json: sonnet-5.json
---

# Zod × Claude Sonnet 5 — findings

## F1 · S3 deprecated · `message` param for custom errors
Model wrote: `z.email({ message: "Please enter a valid email address" })`.
Truth: Zod 4 unified error customization under the `error` param —
`z.email({ error: "Please enter a valid email address" })`. `message` is deprecated;
`invalid_type_error` and `required_error` were dropped entirely.
Cite: https://zod.dev/v4/changelog (Error Customization).

Notable failure shape: the model reached the *v4* top-level format function (`z.email()`)
but paired it with the *v3* error param — a hybrid that no version's docs teach. Half-migrated
beliefs are their own failure mode, and are invisible to anyone checking "does it know v4?"

## F2 · S4 wrong-metadata · unresolved v3/v4 default → emits v3 fallback code
Model could not resolve whether Zod 4 had become the default `zod` install, saying of the import
path: "I'm not fully certain of the exact current state of that import-path split, so I'd treat
this as the part most worth double-checking." It hedged by emitting a commented **Zod 3
alternative** alongside its answer: `z.string().uuid()`, `z.string().email()`,
`z.string().url()`, `result.error.flatten()`.
Truth: `zod` resolves to the v4 line; latest is 4.5.2. The v3 block is dead, wrong-for-current code.
Practical risk: this test gave the model room to hedge. An ordinary coding request ("add a Zod
schema here") gives it no such room, and the v3 branch is live output — including
`result.error.flatten()`, deprecated in v4.
Cite: https://registry.npmjs.org/zod/latest · https://zod.dev/v4/changelog (String Format
Validators; Error Formatting).

## F3 · S4 wrong-metadata · version recency
Believes "Zod 4 is the latest major, GA sometime in 2025," with explicitly low confidence and no
knowledge of the minor line. Truth at test date: 4.5.2. Stated its confidence was "moderate
rather than high" on whether v4 was even stable-by-default yet.
Cite: https://registry.npmjs.org/zod/latest (fetched 2026-08-29).

## Correct under current Zod (unaffected)
Top-level `z.uuid()` / `z.email()` / `z.url()` as the primary answer, two-argument
`z.record(z.string(), z.number())` (with the v3 single-arg form correctly called out as removed),
`z.flattenError()`, `z.infer`, `.partial()`, `.pick({...})`, `z.coerce.number()`,
`import { z } from "zod"`. Zod 3 dated to ~2021 correctly.

## Not recorded as findings (insufficient verification)
- `z.number().int().min(18, "Must be at least 18")` — string-shorthand second argument. Whether
  the bare-string shorthand remains supported in v4 alongside `{ error }` was not verified
  against a primary source this session. Probe in v2 before claiming anything.
