[{"data":1,"prerenderedAt":74},["ShallowReactive",2],{"errors-index":3},[4,9,14,19,24,29,34,39,44,49,54,59,64,69],{"code":5,"path":6,"condition":7,"text":8},"AF01","\u002Fe\u002Faf01","The schema and the adapter disagree on the Zod major version","The schema and the adapter disagree on the Zod major version. How attaform\u002Fzod-v4, attaform\u002Fzod-v3, and the auto-detecting attaform\u002Fzod entry fit together. AF01 The schema you passed comes from a different Zod major than the adapter you imported. In development this reads: attaform\u002Fzod-v4 Schema is not a Zod v4 schema. The attaform\u002Fzod-v4 adapter requires zod@^4. Either: (a) install zod@^4 in your project; (b) import from attaform\u002Fzod , which auto-detects the Zod version (and tree-shakes to a single adapter when the attaform\u002Fvite plugin is active); or (c) import from attaform\u002Fzod-v3 if you are staying on Zod v3. The mirror case fires from attaform\u002Fzod-v3 when it receives a Zod v4 schema. What happened Attaform ships a first-class adapter for each Zod major, and each adapter reads that major's internal schema shape. A z.object(...) built by zod@4 has no meaning to the v3 adapter, and vice versa, so the adapter stops at construction instead of failing somewhere deep in validation. How to fix it Import from attaform\u002Fzod . It detects the installed Zod major and routes to the matching adapter, and the attaform\u002Fvite plugin tree-shakes the unused one. Or align the explicit entry with your install: attaform\u002Fzod-v4 with zod@^4 , attaform\u002Fzod-v3 with zod@^3 . Monorepos: check for two Zod copies. A schema built by one workspace package against zod@3 and validated by another against zod@4 triggers this even though both imports look identical. Entry points walks the full entry map.",{"code":10,"path":11,"condition":12,"text":13},"AF02","\u002Fe\u002Faf02","The schema uses a kind Attaform has no form semantics for","The schema uses a kind Attaform has no form semantics for, such as z.promise, z.map, or z.function. Where the boundary sits and what to reshape. AF02 The schema declares a kind that has no form representation, so the adapter stops at construction. In development this reads: attaform\u002Fzod unsupported kind 'promise' at 'settings.loader' with the offending kind and its path filled in. The production message carries the same two details after the code. What happened A form value has to round-trip through inputs, serialization, and validation. Kinds like z.promise , z.map , z.set , z.symbol , and z.function have no stable input or wire shape, so Attaform refuses them up front, at the exact path, rather than misbehaving later. How to fix it Reshape the field to a representable kind at that path. A Map becomes a record or an array of entries; a lazily loaded value resolves before it enters the form; a callback lives outside the schema entirely. The schema contract lists the supported surface for both Zod majors.",{"code":15,"path":16,"condition":17,"text":18},"AF03","\u002Fe\u002Faf03","The adapter met a Zod kind it does not recognize","The adapter met a Zod kind its supported-kind audit does not recognize, usually after a Zod upgrade introduced a new kind. Update Attaform or report it. AF03 The adapter's supported-kind audit met a kind it does not recognize at all. In development this reads: assertSupportedKinds: unhandled ZodKind 'somekind' What happened At construction the adapter audits every kind in the schema against an exhaustive list: supported kinds pass, known-unsupported kinds raise AF02 . AF03 is the third bucket, a kind outside both lists. In practice that means your installed Zod is newer than the list this Attaform version ships, most often after a Zod minor introduced a brand-new kind. How to fix it Update Attaform; the audit tracks new Zod kinds as they appear. Already on the latest? Open an issue with the kind name from the message and the schema snippet that produced it, and reshape the field to a supported kind in the meantime. The schema contract covers what Attaform asks of a schema and how the adapters read it.",{"code":20,"path":21,"condition":22,"text":23},"AF04","\u002Fe\u002Faf04","`useForm` received an invalid configuration","useForm received an invalid configuration, most often a schema passed directly instead of inside the options object. The one-line fix and the full shape. AF04 useForm received something other than a configuration object with a schema field. In development this reads: attaform useForm received an invalid configuration (a schema directly, no argument, or no schema field). Pass it as useForm({ schema }) — the schema is one of several configuration options. See https:\u002F\u002Fattaform.dev\u002Fdocs\u002Freading-the-form\u002Fthe-form for the full configuration shape. What happened The argument to useForm is an options bag, and the schema is one of several fields on it. Passing the schema directly (or nothing at all) is the most common first-run stumble, so Attaform names it precisely instead of failing deep inside the validator. How to fix it const schema = z. object ({ email: z. string (). email () }) \u002F\u002F Instead of useForm(schema): const form = useForm ({ schema }) The form documents every configuration option. html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"code":25,"path":26,"condition":27,"text":28},"AF05","\u002Fe\u002Faf05","A form key uses the reserved `__atta:` namespace","A useForm key starts with the reserved __atta prefix, which Attaform keeps for library-internal synthetic keys. Pick any other prefix for your form. AF05 The form key you passed starts with __atta: , a namespace Attaform reserves for itself. In development this reads: attaform Form key \"**atta:checkout\" uses the reserved \"**atta:\" namespace. Use a different prefix — \"__atta:\" is for library-internal synthetic keys (anonymous useForm() calls without an explicit key). The production message appends the offending key after the code. What happened Anonymous useForm() calls get a generated key in the __atta: namespace so they never collide with yours. A consumer-supplied key inside that namespace could collide with a generated one, silently sharing state between two unrelated forms, so Attaform rejects it at construction. How to fix it Rename the key. Anything outside __atta: works: useForm({ schema, key: 'checkout' }) . injectForm covers what form keys are for and how a key resolves.",{"code":30,"path":31,"condition":32,"text":33},"AF06","\u002Fe\u002Faf06","`useForm` \u002F `injectForm` ran outside Vue `setup()`","useForm or injectForm was called outside a Vue setup() function, typically from an event handler or async callback that runs after mount. AF06 useForm \u002F injectForm ran outside a Vue setup() context. In development this reads: attaform useForm \u002F injectForm called outside Vue setup(). Move into setup or mount a child component to trigger from an event. What happened Both composables register lifecycle hooks and provide\u002Finject links, which Vue only wires while a component's setup() is running. A call from an event handler, a watcher body, or an awaited continuation has no current instance to attach to. How to fix it Call the composable during setup() and keep the returned form handle around; event handlers then use the handle instead of calling useForm again. For UI that must not exist until an interaction happens, mount a child component on that interaction ( v-if ) and let its own setup() run the composable. The form walks the handle useForm returns and the state it carries.",{"code":35,"path":36,"condition":37,"text":38},"AF07","\u002Fe\u002Faf07","No Attaform registry is attached to the Vue app","An SSR helper ran on a Vue app with no Attaform registry attached. Install createAttaform() in the server entry before renderToString. AF07 renderAttaformState \u002F hydrateAttaformState ran on an app that has no Attaform registry. In development this reads: attaform No registry attached to this Vue app. Component-level useForm \u002F injectForm \u002F useRegister auto-install the registry, but SSR helpers (renderAttaformState, hydrateAttaformState) run outside setup and require an explicit app.use(createAttaform()) at server-render time. Add it to your SSR entry, before renderToString . What happened Inside components, the registry installs itself on first use. The SSR helpers run outside any component, before or after the render, so nothing has installed it for them. Under Nuxt the attaform\u002Fnuxt module wires this automatically; this code almost always points at a bare-Vue SSR entry that skipped the explicit install. How to fix it const app = createSSRApp (App) app. use ( createAttaform ({ ssr: true })) SSR hydration: bare Vue shows the complete server and client entries. html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"code":40,"path":41,"condition":42,"text":43},"AF08","\u002Fe\u002Faf08","A numeric path segment is not a non-negative integer","A numeric path segment was negative or fractional. Array positions in Attaform paths are non-negative integers; the production message appends the value. AF08 A path contained a numeric segment that is not a non-negative integer. In development this reads: Path segments must be non-negative integers when numeric; got -1 The production message appends the offending value after the code. What happened Numeric segments address array positions, so -1 , 1.5 , and NaN have no target. The path canonicalizer rejects them at the boundary, before any read or write runs against the form tree. How to fix it Pass a real index. Computed positions are the usual source; clamp or guard the arithmetic that produced the value before it enters the path: form. setValue ([ 'items' , items. length - 1 , 'name' ], 'last' ) guards items.length > 0 , or the computed index is -1 . setValue patterns covers both path forms, dotted and segment-tuple, and when to reach for each. html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"code":45,"path":46,"condition":47,"text":48},"AF09","\u002Fe\u002Faf09","A dotted path contains an empty segment","A dotted path string contains an empty segment, from a doubled or trailing dot. Use the array path form when a key is genuinely an empty string. AF09 A dotted path string contains an empty segment. In development this reads: Path 'user..email' has an empty segment; use the array form for empty keys. The production message appends the offending path after the code. What happened Splitting 'user..email' (or 'user.' ) on dots produces an empty string between the dots. That is almost always a string-building bug, so the canonicalizer rejects it instead of quietly addressing a field named '' . How to fix it Fix the interpolation that built the path: `${prefix}.${key}` with an empty prefix is the classic case. Addressing a key that genuinely is the empty string? Pass the array form, which needs no separator: form.setValue(['user', '', 'email'], value) . setValue patterns covers both path forms, including the segment-tuple that sidesteps separator pitfalls.",{"code":50,"path":51,"condition":52,"text":53},"AF10","\u002Fe\u002Faf10","`form.rehydrate()` ran without a `defaultValues` factory","form.rehydrate() ran on a form whose defaultValues was not the function form, so there is no factory to re-run. Configure a factory to enable it. AF10 form.rehydrate() was called, but the form has no defaultValues factory to re-run. In development this reads: attaform form.rehydrate(): no defaultValues factory was captured. Configure useForm({ defaultValues: () => ... }) to enable rehydrate. What happened rehydrate re-runs the defaultValues function and resets the form around its fresh result. That contract only exists when defaultValues was passed as a function; a plain object (or nothing) leaves nothing to re-run, so the call throws at the call site rather than resolving to a stale reset. How to fix it const form = useForm ({ schema, defaultValues : () => fetchDraft (id), }) \u002F\u002F Later, when the source data changes: await form. rehydrate () The form covers defaultValues in both shapes. html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"code":55,"path":56,"condition":57,"text":58},"AF11","\u002Fe\u002Faf11","`resetField` could not restore a leaf from originals","resetField could not write a leaf back from originals because the stored value no longer fits the schema slot. An internal invariant worth reporting. AF11 resetField tried to restore a leaf from the form's originals and the write was rejected. In development this reads: attaform resetField: leaf write rejected for path 'items.0.qty' — originals contain a value that doesn't satisfy the slim primitive shape. This is a bug in the construction pipeline. The production message appends the path after the code. What happened Originals are captured by Attaform's own construction pipeline, which guarantees every stored value fits its schema slot. A rejected restore means that guarantee broke somewhere upstream. The reset for that path is skipped; the rest of the form is unaffected. What to do This is an Attaform invariant, not a mistake in your code. Open an issue with the schema for the reported path and the steps that led to the reset, and the pipeline gap gets closed at the source.",{"code":60,"path":61,"condition":62,"text":63},"AF12","\u002Fe\u002Faf12","`resetField` could not restore a subtree from originals","resetField could not write a subtree back from originals because stored values no longer fit their schema slots. An internal invariant worth reporting. AF12 resetField tried to restore a whole subtree from the form's originals and the write was rejected. In development this reads: attaform resetField: subtree write rejected at path 'address' — originals contain values that don't satisfy the slim primitive shape. This is a bug in the construction pipeline. The production message appends the path after the code. What happened Same invariant as AF11 , at container scope: the subtree assembled from originals should always fit the schema, so a rejected write means the construction-time guarantee broke upstream. The reset for that subtree is skipped; the rest of the form is unaffected. What to do Open an issue with the schema for the reported path and the steps that led to the reset. The distinct code (leaf vs subtree) is part of the report's value.",{"code":65,"path":66,"condition":67,"text":68},"AF13","\u002Fe\u002Faf13","The Zod v3 adapter defaulted an unsupported kind to `null`","The Zod v3 adapter met a schema kind it cannot derive a default for and set that field to null. The form still mounts; reshape the field to clear it. AF13 While deriving default values, the Zod v3 adapter met a kind it has no derivation for and defaulted that field to null . In development this reads: attaform zod-v3 adapter: unsupported schema kind 'ZodPromise' on form 'checkout'. Defaulting the field to null. Use a supported zod kind (object\u002Farray\u002Frecord\u002Fstring\u002Fnumber\u002Fetc.) at this path. The production message appends the kind and the form key after the code. What happened This is a warning, not a crash: the form mounts, with null standing in at the affected path. Validation against the real schema will flag that null on submit, so the earlier you reshape the field, the cleaner the run. How to fix it Reshape the field to a kind with a derivable empty value. The schema contract lists the supported surface; AF02 covers the construction-time hard stop for kinds with no form semantics at all.",{"code":70,"path":71,"condition":72,"text":73},"AF14","\u002Fe\u002Faf14","A `register` transform threw and the write was aborted","A register transform threw, so the write was aborted. Production logs redact the details deliberately; development shows the path, index, and error. AF14 A register({ transforms }) function threw while processing a write, and the write was aborted. In development the console shows the full picture: the path, the transform's index and name, a remediation hint, and the original error with its stack. In production the log is exactly the code line you followed here, with none of those details. Why production redacts this Transform bodies are your code, and their thrown errors can embed anything the user just typed. Attaform treats messages and stack frames from inside a transform as an information-leak surface, so the production log is a fixed string. Run the development build to see the original error. How to fix it Transforms must not throw. Wrap recoverable logic in the transform's own try\u002Fcatch and return the fallback you want written: const rv = form. register ( 'amount' , { transforms: [ ( raw ) => { try { return normalizeCurrency (raw) } catch { return raw } }, ], }) Transforms covers the pipeline, including async transforms, whose rejections surface on field.transformError instead of the console. html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",1787641550974]