[{"data":1,"prerenderedAt":712},["ShallowReactive",2],{"content-\u002Fdocs\u002Fdevtools-and-debugging\u002Ftroubleshooting":3},{"id":4,"title":5,"body":6,"description":704,"extension":705,"meta":706,"metaRows":707,"navigation":286,"path":708,"seo":709,"source":707,"stem":710,"__hash__":711},"docs\u002Fdocs\u002Fdevtools-and-debugging\u002Ftroubleshooting.md","Troubleshooting",{"type":7,"value":8,"toc":692},"minimark",[9,13,20,25,28,86,98,101,137,144,154,331,335,359,370,500,507,511,518,567,571,574,640,644,651,658,662,688],[10,11,5],"h1",{"id":12},"troubleshooting",[14,15,16],"blockquote",{},[17,18,19],"p",{},"Symptom first, fix second. The most common stumbling blocks readers hit in the first month.",[21,22,24],"h2",{"id":23},"my-field-doesnt-validate","\"My field doesn't validate\"",[17,26,27],{},"Three independent causes:",[29,30,31,44,64],"ul",{},[32,33,34,38,39,43],"li",{},[35,36,37],"strong",{},"The schema doesn't include the field."," A ",[40,41,42],"code",{},"z.string().optional()"," wrapper without an inner refinement accepts everything. Verify the schema.",[32,45,46,57,58,60,61,63],{},[35,47,48,49,52,53,56],{},"You're in ",[40,50,51],{},"strict: false"," and watching ",[40,54,55],{},"validate()","."," Lax mode strips refinements during default-values derivation so the form mounts with empty values without failing; refinements re-apply on submit. Drop the ",[40,59,51],{}," opt-out if you want ",[40,62,55],{}," to fire refinements immediately.",[32,65,66,69,70,73,74,77,78,81,82,85],{},[35,67,68],{},"The path doesn't match the schema."," ",[40,71,72],{},"'items.0.name'"," and ",[40,75,76],{},"['items', 0, 'name']"," canonicalize to the same path. But ",[40,79,80],{},"['items', '0', 'name']"," (string ",[40,83,84],{},"'0'",") does NOT; emit numbers when the position is an array index.",[21,87,89,90,93,94,97],{"id":88},"registeremail-returns-a-never-typed-value","\"",[40,91,92],{},"register('email')"," returns a ",[40,95,96],{},"never","-typed value\"",[17,99,100],{},"The schema generic couldn't be inferred. Two likely causes:",[29,102,103,114],{},[32,104,105,106,109,110,113],{},"Your schema is typed as bare ",[40,107,108],{},"ZodObject"," without its concrete shape. Use the literal (",[40,111,112],{},"z.object({ email: z.string() })",") or give the variable a precise type.",[32,115,116,117,120,121,124,125,128,129,132,133,136],{},"You imported ",[40,118,119],{},"useForm"," from ",[40,122,123],{},"attaform"," (the schema-agnostic core entry) but passed a Zod schema directly. Import from ",[40,126,127],{},"attaform\u002Fzod",", ",[40,130,131],{},"attaform\u002Fzod-v3",", or ",[40,134,135],{},"attaform\u002Fzod-v4"," instead.",[21,138,89,140,143],{"id":139},"handlesubmit-doesnt-run-when-i-submit-the-form",[40,141,142],{},"handleSubmit"," doesn't run when I submit the form\"",[17,145,146,149,150,153],{},[40,147,148],{},"form.handleSubmit(onSubmit)"," returns the ",[35,151,152],{},"handler function",", not a Promise. Bind the returned value:",[155,156,161],"pre",{"className":157,"code":158,"language":159,"meta":160,"style":160},"language-vue shiki shiki-themes github-light github-dark","\u003Cscript setup lang=\"ts\">\n  const form = useForm({ schema })\n  const onSubmit = form.handleSubmit(async (values) => {\n    await api.signup(values)\n  })\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cform @submit.prevent=\"onSubmit\">...\u003C\u002Fform>\n\u003C\u002Ftemplate>\n","vue","",[40,162,163,193,213,250,265,271,281,288,298,322],{"__ignoreMap":160},[164,165,168,172,176,180,183,186,190],"span",{"class":166,"line":167},"line",1,[164,169,171],{"class":170},"sVt8B","\u003C",[164,173,175],{"class":174},"s9eBZ","script",[164,177,179],{"class":178},"sScJk"," setup",[164,181,182],{"class":178}," lang",[164,184,185],{"class":170},"=",[164,187,189],{"class":188},"sZZnC","\"ts\"",[164,191,192],{"class":170},">\n",[164,194,196,200,204,207,210],{"class":166,"line":195},2,[164,197,199],{"class":198},"szBVR","  const",[164,201,203],{"class":202},"sj4cs"," form",[164,205,206],{"class":198}," =",[164,208,209],{"class":178}," useForm",[164,211,212],{"class":170},"({ schema })\n",[164,214,216,218,221,223,226,228,231,234,237,241,244,247],{"class":166,"line":215},3,[164,217,199],{"class":198},[164,219,220],{"class":202}," onSubmit",[164,222,206],{"class":198},[164,224,225],{"class":170}," form.",[164,227,142],{"class":178},[164,229,230],{"class":170},"(",[164,232,233],{"class":198},"async",[164,235,236],{"class":170}," (",[164,238,240],{"class":239},"s4XuR","values",[164,242,243],{"class":170},") ",[164,245,246],{"class":198},"=>",[164,248,249],{"class":170}," {\n",[164,251,253,256,259,262],{"class":166,"line":252},4,[164,254,255],{"class":198},"    await",[164,257,258],{"class":170}," api.",[164,260,261],{"class":178},"signup",[164,263,264],{"class":170},"(values)\n",[164,266,268],{"class":166,"line":267},5,[164,269,270],{"class":170},"  })\n",[164,272,274,277,279],{"class":166,"line":273},6,[164,275,276],{"class":170},"\u003C\u002F",[164,278,175],{"class":174},[164,280,192],{"class":170},[164,282,284],{"class":166,"line":283},7,[164,285,287],{"emptyLinePlaceholder":286},true,"\n",[164,289,291,293,296],{"class":166,"line":290},8,[164,292,171],{"class":170},[164,294,295],{"class":174},"template",[164,297,192],{"class":170},[164,299,301,304,307,310,312,315,318,320],{"class":166,"line":300},9,[164,302,303],{"class":170},"  \u003C",[164,305,306],{"class":174},"form",[164,308,309],{"class":178}," @submit.prevent",[164,311,185],{"class":170},[164,313,314],{"class":188},"\"onSubmit\"",[164,316,317],{"class":170},">...\u003C\u002F",[164,319,306],{"class":174},[164,321,192],{"class":170},[164,323,325,327,329],{"class":166,"line":324},10,[164,326,276],{"class":170},[164,328,295],{"class":174},[164,330,192],{"class":170},[21,332,334],{"id":333},"v-register-on-my-component-does-nothing","\"v-register on my component does nothing\"",[17,336,337,340,341,128,344,132,347,350,351,354,355,358],{},[40,338,339],{},"\u003CMyComponent v-register=\"...\">"," works only when the component's rendered root element is one Vue's directive can bind: ",[40,342,343],{},"\u003Cinput>",[40,345,346],{},"\u003Ctextarea>",[40,348,349],{},"\u003Cselect>",". For components whose root is a ",[40,352,353],{},"\u003Cdiv>"," \u002F ",[40,356,357],{},"\u003Clabel>"," \u002F styled wrapper, the directive skips listener attachment to avoid the bubbled-write bug.",[17,360,361,362,365,366,369],{},"The fix: call ",[40,363,364],{},"useRegister()"," in the child's setup and re-bind ",[40,367,368],{},"v-register"," onto an inner native element:",[155,371,373],{"className":157,"code":372,"language":159,"meta":160,"style":160},"\u003C!-- StyledInput.vue -->\n\u003Cscript setup lang=\"ts\">\n  import { useRegister } from 'attaform'\n  const rv = useRegister()\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv class=\"wrapper\">\n    \u003Cinput v-register=\"rv\" \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",[40,374,375,381,397,411,426,434,438,446,463,482,491],{"__ignoreMap":160},[164,376,377],{"class":166,"line":167},[164,378,380],{"class":379},"sJ8bj","\u003C!-- StyledInput.vue -->\n",[164,382,383,385,387,389,391,393,395],{"class":166,"line":195},[164,384,171],{"class":170},[164,386,175],{"class":174},[164,388,179],{"class":178},[164,390,182],{"class":178},[164,392,185],{"class":170},[164,394,189],{"class":188},[164,396,192],{"class":170},[164,398,399,402,405,408],{"class":166,"line":215},[164,400,401],{"class":198},"  import",[164,403,404],{"class":170}," { useRegister } ",[164,406,407],{"class":198},"from",[164,409,410],{"class":188}," 'attaform'\n",[164,412,413,415,418,420,423],{"class":166,"line":252},[164,414,199],{"class":198},[164,416,417],{"class":202}," rv",[164,419,206],{"class":198},[164,421,422],{"class":178}," useRegister",[164,424,425],{"class":170},"()\n",[164,427,428,430,432],{"class":166,"line":267},[164,429,276],{"class":170},[164,431,175],{"class":174},[164,433,192],{"class":170},[164,435,436],{"class":166,"line":273},[164,437,287],{"emptyLinePlaceholder":286},[164,439,440,442,444],{"class":166,"line":283},[164,441,171],{"class":170},[164,443,295],{"class":174},[164,445,192],{"class":170},[164,447,448,450,453,456,458,461],{"class":166,"line":290},[164,449,303],{"class":170},[164,451,452],{"class":174},"div",[164,454,455],{"class":178}," class",[164,457,185],{"class":170},[164,459,460],{"class":188},"\"wrapper\"",[164,462,192],{"class":170},[164,464,465,468,471,474,476,479],{"class":166,"line":300},[164,466,467],{"class":170},"    \u003C",[164,469,470],{"class":174},"input",[164,472,473],{"class":178}," v-register",[164,475,185],{"class":170},[164,477,478],{"class":188},"\"rv\"",[164,480,481],{"class":170}," \u002F>\n",[164,483,484,487,489],{"class":166,"line":324},[164,485,486],{"class":170},"  \u003C\u002F",[164,488,452],{"class":174},[164,490,192],{"class":170},[164,492,494,496,498],{"class":166,"line":493},11,[164,495,276],{"class":170},[164,497,295],{"class":174},[164,499,192],{"class":170},[17,501,502,503,506],{},"The dev-mode console warning ",[40,504,505],{},"v-register on \u003Cdiv> is a no-op …"," points here.",[21,508,510],{"id":509},"submit-fails-with-no-value-supplied-on-a-field-the-user-can-leave-blank","\"Submit fails with 'No value supplied' on a field the user can leave blank\"",[17,512,513,514,517],{},"The path is in the form's ",[40,515,516],{},"blankPaths"," set and bound to a required schema. Three resolutions:",[29,519,520,534,548],{},[32,521,522,525,526,128,528,132,531,56],{},[35,523,524],{},"The field is genuinely optional."," Wrap the schema: ",[40,527,42],{},[40,529,530],{},"z.number().nullable()",[40,532,533],{},"z.string().default('')",[32,535,536,543,544,547],{},[35,537,538,539,542],{},"The field is required but ",[40,540,541],{},"''"," should count as \"filled\"."," Supply an explicit default: ",[40,545,546],{},"defaultValues: { email: '' }",". Attaform reads this as \"empty string is intentional\" and skips the auto-mark for that leaf.",[32,549,550,553,554,557,558,354,561,354,563,566],{},[35,551,552],{},"Attaform should treat a blank field as \"user didn't fill it.\""," Working as intended; the synthesized error (",[40,555,556],{},"code: 'atta:no-value-supplied'",") prevents silently submitting ",[40,559,560],{},"0",[40,562,541],{},[40,564,565],{},"false"," for an unfilled required field.",[21,568,570],{"id":569},"hydration-mismatch-after-ssr","\"Hydration mismatch after SSR\"",[17,572,573],{},"Three usual suspects:",[29,575,576,590,620],{},[32,577,578,589],{},[35,579,580,581,584,585,588],{},"Did you call ",[40,582,583],{},"hydrateAttaformState(app, payload)"," before ",[40,586,587],{},"app.mount(...)","?"," It has to land before setup runs. Nuxt does this automatically.",[32,591,592,69,595,128,598,128,601,128,604,607,608,611,612,615,616,619],{},[35,593,594],{},"Non-JSON-safe value in the form?",[40,596,597],{},"Date",[40,599,600],{},"Map",[40,602,603],{},"Set",[40,605,606],{},"BigInt",", and circular refs don't survive ",[40,609,610],{},"JSON.stringify",". Coerce at the form boundary (",[40,613,614],{},"z.date().transform((d) => d.toISOString())",") or use Nuxt's ",[40,617,618],{},"devalue","-based payload (automatic under Nuxt).",[32,621,622,628,629,632,633,636,637,639],{},[35,623,624,627],{},[40,625,626],{},"escapeForInlineScript"," missing on the bare-Vue side?"," A form value containing ",[40,630,631],{},"\u003C\u002Fscript>"," breaks the inline payload. Wrap ",[40,634,635],{},"JSON.stringify(payload)"," in ",[40,638,626],{},". Not required under Nuxt.",[21,641,643],{"id":642},"persisted-state-is-gone-after-a-schema-change","\"Persisted state is gone after a schema change\"",[17,645,646,647,650],{},"Working as intended. Storage keys carry the schema's fingerprint: when the schema changes shape, the fingerprint changes, the old key becomes unreachable, and the orphan-cleanup pass on the next mount removes it. No manual ",[40,648,649],{},"version"," bump needed.",[17,652,653,654,657],{},"To invalidate drafts without changing the schema (e.g. shipping a security fix that requires fresh state), call ",[40,655,656],{},"form.clearPersistedDraft()"," on mount.",[21,659,661],{"id":660},"where-to-next","Where to next",[29,663,664,672,681],{},[32,665,666,671],{},[667,668,670],"a",{"href":669},"\u002Fdocs\u002Freading-the-form\u002Fthe-form","The form",": the full reactive surface.",[32,673,674,680],{},[667,675,677],{"href":676},"\u002Fdocs\u002Freading-the-form\u002Ferrors",[40,678,679],{},"errors",": per-path error reads.",[32,682,683,687],{},[667,684,686],{"href":685},"\u002Fdocs\u002Fpersistence\u002Foverview","Persistence overview",": the dual opt-in model and storage backends.",[689,690,691],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}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 .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 .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);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":160,"searchDepth":195,"depth":195,"links":693},[694,695,697,699,700,701,702,703],{"id":23,"depth":195,"text":24},{"id":88,"depth":195,"text":696},"\"register('email') returns a never-typed value\"",{"id":139,"depth":195,"text":698},"\"handleSubmit doesn't run when I submit the form\"",{"id":333,"depth":195,"text":334},{"id":509,"depth":195,"text":510},{"id":569,"depth":195,"text":570},{"id":642,"depth":195,"text":643},{"id":660,"depth":195,"text":661},"Common Attaform pitfalls and how to fix them. Shared-form key collisions, missing v-register elements, hydration drift, handleSubmit bindings, never-typed register reads.","md",{},null,"\u002Fdocs\u002Fdevtools-and-debugging\u002Ftroubleshooting",{"title":5,"description":704},"docs\u002Fdevtools-and-debugging\u002Ftroubleshooting","3OcL3l2wY3URMlRNJycIhX-pw9c_G8dT6l7BLHwct2M",1780949755303]