[{"data":1,"prerenderedAt":2020},["ShallowReactive",2],{"content-\u002Fdocs\u002Frecipes\u002Fserver-errors":3},{"id":4,"title":5,"body":6,"description":2013,"extension":2014,"meta":2015,"navigation":112,"path":2016,"seo":2017,"stem":2018,"__hash__":2019},"docs\u002Fdocs\u002Frecipes\u002Fserver-errors.md","Server errors (HTTP 4xx validation failures)",{"type":7,"value":8,"toc":2002},"minimark",[9,13,34,39,590,593,610,617,621,626,691,718,783,787,803,806,918,921,994,1007,1023,1039,1045,1168,1191,1195,1198,1203,1368,1372,1375,1560,1574,1578,1587,1683,1740,1744,1747,1756,1802,1815,1821,1831,1998],[10,11,5],"h1",{"id":12},"server-errors-http-4xx-validation-failures",[14,15,16,17,21,22,25,26,29,30,33],"p",{},"Server-side rules the client doesn't know — \"email already taken\",\n\"coupon expired\", \"we couldn't reach the payment provider\" — surface\nas ",[18,19,20],"code",{},"errors"," via a two-step pattern: parse the payload with\n",[18,23,24],{},"parseApiErrors",", write the result with ",[18,27,28],{},"setFieldErrors"," (or\n",[18,31,32],{},"addFieldErrors",").",[35,36,38],"h2",{"id":37},"the-usual-case","The usual case",[40,41,46],"pre",{"className":42,"code":43,"language":44,"meta":45,"style":45},"language-vue shiki shiki-themes github-light github-dark","\u003Cscript setup lang=\"ts\">\n  import { useForm, parseApiErrors } from 'attaform'\n  import { z } from 'zod'\n\n  const schema = z.object({\n    email: z.email(),\n    password: z.string().min(8),\n  })\n\n  const form = useForm({ schema, key: 'signup' })\n\n  const onSubmit = form.handleSubmit(async (values) => {\n    try {\n      await $fetch('\u002Fapi\u002Fsignup', { method: 'POST', body: values })\n    } catch (err: any) {\n      if (err.statusCode === 422) {\n        const result = parseApiErrors(err.data, { formKey: form.key })\n        if (result.ok) form.setFieldErrors(result.errors)\n        return\n      }\n      throw err \u002F\u002F Other errors flow through to `meta.submitError`.\n    }\n  })\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cform @submit.prevent=\"onSubmit\">\n    \u003Cinput v-register=\"form.register('email')\" \u002F>\n    \u003Csmall v-if=\"form.errors.email?.[0]\">\n      {{ form.errors.email[0].message }}\n    \u003C\u002Fsmall>\n\n    \u003Cinput v-register=\"form.register('password')\" type=\"password\" \u002F>\n    \u003Csmall v-if=\"form.errors.password?.[0]\">\n      {{ form.errors.password[0].message }}\n    \u003C\u002Fsmall>\n\n    \u003Cbutton :disabled=\"form.meta.isSubmitting\">Sign up\u003C\u002Fbutton>\n  \u003C\u002Fform>\n\u003C\u002Ftemplate>\n","vue","",[18,47,48,78,94,107,114,136,148,172,178,183,205,210,247,255,278,301,318,335,349,355,361,374,380,385,395,400,410,429,449,467,473,483,488,512,528,534,543,548,571,581],{"__ignoreMap":45},[49,50,53,57,61,65,68,71,75],"span",{"class":51,"line":52},"line",1,[49,54,56],{"class":55},"sVt8B","\u003C",[49,58,60],{"class":59},"s9eBZ","script",[49,62,64],{"class":63},"sScJk"," setup",[49,66,67],{"class":63}," lang",[49,69,70],{"class":55},"=",[49,72,74],{"class":73},"sZZnC","\"ts\"",[49,76,77],{"class":55},">\n",[49,79,81,85,88,91],{"class":51,"line":80},2,[49,82,84],{"class":83},"szBVR","  import",[49,86,87],{"class":55}," { useForm, parseApiErrors } ",[49,89,90],{"class":83},"from",[49,92,93],{"class":73}," 'attaform'\n",[49,95,97,99,102,104],{"class":51,"line":96},3,[49,98,84],{"class":83},[49,100,101],{"class":55}," { z } ",[49,103,90],{"class":83},[49,105,106],{"class":73}," 'zod'\n",[49,108,110],{"class":51,"line":109},4,[49,111,113],{"emptyLinePlaceholder":112},true,"\n",[49,115,117,120,124,127,130,133],{"class":51,"line":116},5,[49,118,119],{"class":83},"  const",[49,121,123],{"class":122},"sj4cs"," schema",[49,125,126],{"class":83}," =",[49,128,129],{"class":55}," z.",[49,131,132],{"class":63},"object",[49,134,135],{"class":55},"({\n",[49,137,139,142,145],{"class":51,"line":138},6,[49,140,141],{"class":55},"    email: z.",[49,143,144],{"class":63},"email",[49,146,147],{"class":55},"(),\n",[49,149,151,154,157,160,163,166,169],{"class":51,"line":150},7,[49,152,153],{"class":55},"    password: z.",[49,155,156],{"class":63},"string",[49,158,159],{"class":55},"().",[49,161,162],{"class":63},"min",[49,164,165],{"class":55},"(",[49,167,168],{"class":122},"8",[49,170,171],{"class":55},"),\n",[49,173,175],{"class":51,"line":174},8,[49,176,177],{"class":55},"  })\n",[49,179,181],{"class":51,"line":180},9,[49,182,113],{"emptyLinePlaceholder":112},[49,184,186,188,191,193,196,199,202],{"class":51,"line":185},10,[49,187,119],{"class":83},[49,189,190],{"class":122}," form",[49,192,126],{"class":83},[49,194,195],{"class":63}," useForm",[49,197,198],{"class":55},"({ schema, key: ",[49,200,201],{"class":73},"'signup'",[49,203,204],{"class":55}," })\n",[49,206,208],{"class":51,"line":207},11,[49,209,113],{"emptyLinePlaceholder":112},[49,211,213,215,218,220,223,226,228,231,234,238,241,244],{"class":51,"line":212},12,[49,214,119],{"class":83},[49,216,217],{"class":122}," onSubmit",[49,219,126],{"class":83},[49,221,222],{"class":55}," form.",[49,224,225],{"class":63},"handleSubmit",[49,227,165],{"class":55},[49,229,230],{"class":83},"async",[49,232,233],{"class":55}," (",[49,235,237],{"class":236},"s4XuR","values",[49,239,240],{"class":55},") ",[49,242,243],{"class":83},"=>",[49,245,246],{"class":55}," {\n",[49,248,250,253],{"class":51,"line":249},13,[49,251,252],{"class":83},"    try",[49,254,246],{"class":55},[49,256,258,261,264,266,269,272,275],{"class":51,"line":257},14,[49,259,260],{"class":83},"      await",[49,262,263],{"class":63}," $fetch",[49,265,165],{"class":55},[49,267,268],{"class":73},"'\u002Fapi\u002Fsignup'",[49,270,271],{"class":55},", { method: ",[49,273,274],{"class":73},"'POST'",[49,276,277],{"class":55},", body: values })\n",[49,279,281,284,287,289,292,295,298],{"class":51,"line":280},15,[49,282,283],{"class":55},"    } ",[49,285,286],{"class":83},"catch",[49,288,233],{"class":55},[49,290,291],{"class":236},"err",[49,293,294],{"class":83},":",[49,296,297],{"class":122}," any",[49,299,300],{"class":55},") {\n",[49,302,304,307,310,313,316],{"class":51,"line":303},16,[49,305,306],{"class":83},"      if",[49,308,309],{"class":55}," (err.statusCode ",[49,311,312],{"class":83},"===",[49,314,315],{"class":122}," 422",[49,317,300],{"class":55},[49,319,321,324,327,329,332],{"class":51,"line":320},17,[49,322,323],{"class":83},"        const",[49,325,326],{"class":122}," result",[49,328,126],{"class":83},[49,330,331],{"class":63}," parseApiErrors",[49,333,334],{"class":55},"(err.data, { formKey: form.key })\n",[49,336,338,341,344,346],{"class":51,"line":337},18,[49,339,340],{"class":83},"        if",[49,342,343],{"class":55}," (result.ok) form.",[49,345,28],{"class":63},[49,347,348],{"class":55},"(result.errors)\n",[49,350,352],{"class":51,"line":351},19,[49,353,354],{"class":83},"        return\n",[49,356,358],{"class":51,"line":357},20,[49,359,360],{"class":55},"      }\n",[49,362,364,367,370],{"class":51,"line":363},21,[49,365,366],{"class":83},"      throw",[49,368,369],{"class":55}," err ",[49,371,373],{"class":372},"sJ8bj","\u002F\u002F Other errors flow through to `meta.submitError`.\n",[49,375,377],{"class":51,"line":376},22,[49,378,379],{"class":55},"    }\n",[49,381,383],{"class":51,"line":382},23,[49,384,177],{"class":55},[49,386,388,391,393],{"class":51,"line":387},24,[49,389,390],{"class":55},"\u003C\u002F",[49,392,60],{"class":59},[49,394,77],{"class":55},[49,396,398],{"class":51,"line":397},25,[49,399,113],{"emptyLinePlaceholder":112},[49,401,403,405,408],{"class":51,"line":402},26,[49,404,56],{"class":55},[49,406,407],{"class":59},"template",[49,409,77],{"class":55},[49,411,413,416,419,422,424,427],{"class":51,"line":412},27,[49,414,415],{"class":55},"  \u003C",[49,417,418],{"class":59},"form",[49,420,421],{"class":63}," @submit.prevent",[49,423,70],{"class":55},[49,425,426],{"class":73},"\"onSubmit\"",[49,428,77],{"class":55},[49,430,432,435,438,441,443,446],{"class":51,"line":431},28,[49,433,434],{"class":55},"    \u003C",[49,436,437],{"class":59},"input",[49,439,440],{"class":63}," v-register",[49,442,70],{"class":55},[49,444,445],{"class":73},"\"form.register('email')\"",[49,447,448],{"class":55}," \u002F>\n",[49,450,452,454,457,460,462,465],{"class":51,"line":451},29,[49,453,434],{"class":55},[49,455,456],{"class":59},"small",[49,458,459],{"class":63}," v-if",[49,461,70],{"class":55},[49,463,464],{"class":73},"\"form.errors.email?.[0]\"",[49,466,77],{"class":55},[49,468,470],{"class":51,"line":469},30,[49,471,472],{"class":55},"      {{ form.errors.email[0].message }}\n",[49,474,476,479,481],{"class":51,"line":475},31,[49,477,478],{"class":55},"    \u003C\u002F",[49,480,456],{"class":59},[49,482,77],{"class":55},[49,484,486],{"class":51,"line":485},32,[49,487,113],{"emptyLinePlaceholder":112},[49,489,491,493,495,497,499,502,505,507,510],{"class":51,"line":490},33,[49,492,434],{"class":55},[49,494,437],{"class":59},[49,496,440],{"class":63},[49,498,70],{"class":55},[49,500,501],{"class":73},"\"form.register('password')\"",[49,503,504],{"class":63}," type",[49,506,70],{"class":55},[49,508,509],{"class":73},"\"password\"",[49,511,448],{"class":55},[49,513,515,517,519,521,523,526],{"class":51,"line":514},34,[49,516,434],{"class":55},[49,518,456],{"class":59},[49,520,459],{"class":63},[49,522,70],{"class":55},[49,524,525],{"class":73},"\"form.errors.password?.[0]\"",[49,527,77],{"class":55},[49,529,531],{"class":51,"line":530},35,[49,532,533],{"class":55},"      {{ form.errors.password[0].message }}\n",[49,535,537,539,541],{"class":51,"line":536},36,[49,538,478],{"class":55},[49,540,456],{"class":59},[49,542,77],{"class":55},[49,544,546],{"class":51,"line":545},37,[49,547,113],{"emptyLinePlaceholder":112},[49,549,551,553,556,559,561,564,567,569],{"class":51,"line":550},38,[49,552,434],{"class":55},[49,554,555],{"class":59},"button",[49,557,558],{"class":63}," :disabled",[49,560,70],{"class":55},[49,562,563],{"class":73},"\"form.meta.isSubmitting\"",[49,565,566],{"class":55},">Sign up\u003C\u002F",[49,568,555],{"class":59},[49,570,77],{"class":55},[49,572,574,577,579],{"class":51,"line":573},39,[49,575,576],{"class":55},"  \u003C\u002F",[49,578,418],{"class":59},[49,580,77],{"class":55},[49,582,584,586,588],{"class":51,"line":583},40,[49,585,390],{"class":55},[49,587,407],{"class":59},[49,589,77],{"class":55},[14,591,592],{},"By the time your callback runs, client-side schema validation has\nalready passed — this is genuinely for server-only failures.",[14,594,595,599,600,602,603,605,606,609],{},[596,597,598],"strong",{},"API-injected errors persist"," across schema revalidation and\nsuccessful submits. ",[18,601,28],{}," and ",[18,604,32],{}," write to\na separate user-error store (internally distinct from the\nschema-validation pipeline's store); nothing automatically clears\nthem. The user's next keystroke will re-run schema validation\nagainst the field — that updates the schema-error half, but your\nAPI entries stay until you call ",[18,607,608],{},"clearFieldErrors(path)"," (or\nunmount the form).",[14,611,612,613,616],{},"The two flavours surface together in ",[18,614,615],{},"errors[path]"," (schema\nentries first, user entries second), so templates render both\nwithout branching.",[35,618,620],{"id":619},"the-result-type","The result type",[14,622,623,625],{},[18,624,24],{}," returns a discriminated result so you can detect\nmalformed payloads without try\u002Fcatch:",[40,627,631],{"className":628,"code":629,"language":630,"meta":45,"style":45},"language-ts shiki shiki-themes github-light github-dark","type ParseApiErrorsResult = {\n  readonly ok: boolean\n  readonly errors: ValidationError[]\n  readonly rejected?: string\n}\n","ts",[18,632,633,645,658,673,686],{"__ignoreMap":45},[49,634,635,638,641,643],{"class":51,"line":52},[49,636,637],{"class":83},"type",[49,639,640],{"class":63}," ParseApiErrorsResult",[49,642,126],{"class":83},[49,644,246],{"class":55},[49,646,647,650,653,655],{"class":51,"line":80},[49,648,649],{"class":83},"  readonly",[49,651,652],{"class":236}," ok",[49,654,294],{"class":83},[49,656,657],{"class":122}," boolean\n",[49,659,660,662,665,667,670],{"class":51,"line":96},[49,661,649],{"class":83},[49,663,664],{"class":236}," errors",[49,666,294],{"class":83},[49,668,669],{"class":63}," ValidationError",[49,671,672],{"class":55},"[]\n",[49,674,675,677,680,683],{"class":51,"line":109},[49,676,649],{"class":83},[49,678,679],{"class":236}," rejected",[49,681,682],{"class":83},"?:",[49,684,685],{"class":122}," string\n",[49,687,688],{"class":51,"line":116},[49,689,690],{"class":55},"}\n",[692,693,694,704],"ul",{},[695,696,697,700,701,703],"li",{},[18,698,699],{},"{ ok: true, errors }"," — payload recognised. ",[18,702,20],{}," may be\nempty (server returned a 422 with no field-level details).",[695,705,706,709,710,713,714,717],{},[18,707,708],{},"{ ok: false, errors: [], rejected }"," — payload shape wasn't\nrecognised. ",[18,711,712],{},"rejected"," carries a reason (\"payload was string,\nexpected object\", \"entries must be ",[18,715,716],{},"{ message, code }"," objects\",\netc.). Log it; don't apply.",[40,719,721],{"className":628,"code":720,"language":630,"meta":45,"style":45},"const result = parseApiErrors(err.data, { formKey: form.key })\nif (result.ok) {\n  form.setFieldErrors(result.errors)\n} else {\n  console.error('Unexpected error payload:', result.rejected, err.data)\n}\n",[18,722,723,736,744,753,763,779],{"__ignoreMap":45},[49,724,725,728,730,732,734],{"class":51,"line":52},[49,726,727],{"class":83},"const",[49,729,326],{"class":122},[49,731,126],{"class":83},[49,733,331],{"class":63},[49,735,334],{"class":55},[49,737,738,741],{"class":51,"line":80},[49,739,740],{"class":83},"if",[49,742,743],{"class":55}," (result.ok) {\n",[49,745,746,749,751],{"class":51,"line":96},[49,747,748],{"class":55},"  form.",[49,750,28],{"class":63},[49,752,348],{"class":55},[49,754,755,758,761],{"class":51,"line":109},[49,756,757],{"class":55},"} ",[49,759,760],{"class":83},"else",[49,762,246],{"class":55},[49,764,765,768,771,773,776],{"class":51,"line":116},[49,766,767],{"class":55},"  console.",[49,769,770],{"class":63},"error",[49,772,165],{"class":55},[49,774,775],{"class":73},"'Unexpected error payload:'",[49,777,778],{"class":55},", result.rejected, err.data)\n",[49,780,781],{"class":51,"line":138},[49,782,690],{"class":55},[35,784,786],{"id":785},"payload-shapes","Payload shapes",[14,788,789,790,792,793,795,796,799,800,802],{},"Every entry is ",[18,791,716],{}," (both required). The ",[18,794,18],{}," is\nforwarded verbatim onto the produced ",[18,797,798],{},"ValidationError"," so error\nrenderers branch on ",[18,801,18],{}," instead of message strings.",[14,804,805],{},"A wrapped envelope:",[40,807,809],{"className":628,"code":808,"language":630,"meta":45,"style":45},"{\n  error: {\n    details: {\n      email: { message: 'already taken', code: 'api:duplicate-email' },\n      password: [\n        { message: 'too short', code: 'api:min-length' },\n        { message: 'must contain a digit', code: 'api:digit-required' },\n      ],\n    },\n  },\n}\n",[18,810,811,816,824,831,861,869,885,899,904,909,914],{"__ignoreMap":45},[49,812,813],{"class":51,"line":52},[49,814,815],{"class":55},"{\n",[49,817,818,821],{"class":51,"line":80},[49,819,820],{"class":63},"  error",[49,822,823],{"class":55},": {\n",[49,825,826,829],{"class":51,"line":96},[49,827,828],{"class":63},"    details",[49,830,823],{"class":55},[49,832,833,836,839,842,845,848,851,853,855,858],{"class":51,"line":109},[49,834,835],{"class":63},"      email",[49,837,838],{"class":55},": { ",[49,840,841],{"class":63},"message",[49,843,844],{"class":55},": ",[49,846,847],{"class":73},"'already taken'",[49,849,850],{"class":55},", ",[49,852,18],{"class":63},[49,854,844],{"class":55},[49,856,857],{"class":73},"'api:duplicate-email'",[49,859,860],{"class":55}," },\n",[49,862,863,866],{"class":51,"line":116},[49,864,865],{"class":63},"      password",[49,867,868],{"class":55},": [\n",[49,870,871,874,877,880,883],{"class":51,"line":138},[49,872,873],{"class":55},"        { message: ",[49,875,876],{"class":73},"'too short'",[49,878,879],{"class":55},", code: ",[49,881,882],{"class":73},"'api:min-length'",[49,884,860],{"class":55},[49,886,887,889,892,894,897],{"class":51,"line":150},[49,888,873],{"class":55},[49,890,891],{"class":73},"'must contain a digit'",[49,893,879],{"class":55},[49,895,896],{"class":73},"'api:digit-required'",[49,898,860],{"class":55},[49,900,901],{"class":51,"line":174},[49,902,903],{"class":55},"      ],\n",[49,905,906],{"class":51,"line":180},[49,907,908],{"class":55},"    },\n",[49,910,911],{"class":51,"line":185},[49,912,913],{"class":55},"  },\n",[49,915,916],{"class":51,"line":207},[49,917,690],{"class":55},[14,919,920],{},"A bare details record works the same way:",[40,922,924],{"className":628,"code":923,"language":630,"meta":45,"style":45},"{\n  email: { message: 'already taken', code: 'api:duplicate-email' },\n  password: [\n    { message: 'too short', code: 'api:min-length' },\n    { message: 'must contain a digit', code: 'api:digit-required' },\n  ],\n}\n",[18,925,926,930,953,960,973,985,990],{"__ignoreMap":45},[49,927,928],{"class":51,"line":52},[49,929,815],{"class":55},[49,931,932,935,937,939,941,943,945,947,949,951],{"class":51,"line":80},[49,933,934],{"class":63},"  email",[49,936,838],{"class":55},[49,938,841],{"class":63},[49,940,844],{"class":55},[49,942,847],{"class":73},[49,944,850],{"class":55},[49,946,18],{"class":63},[49,948,844],{"class":55},[49,950,857],{"class":73},[49,952,860],{"class":55},[49,954,955,958],{"class":51,"line":96},[49,956,957],{"class":63},"  password",[49,959,868],{"class":55},[49,961,962,965,967,969,971],{"class":51,"line":109},[49,963,964],{"class":55},"    { message: ",[49,966,876],{"class":73},[49,968,879],{"class":55},[49,970,882],{"class":73},[49,972,860],{"class":55},[49,974,975,977,979,981,983],{"class":51,"line":116},[49,976,964],{"class":55},[49,978,891],{"class":73},[49,980,879],{"class":55},[49,982,896],{"class":73},[49,984,860],{"class":55},[49,986,987],{"class":51,"line":138},[49,988,989],{"class":55},"  ],\n",[49,991,992],{"class":51,"line":150},[49,993,690],{"class":55},[14,995,996,997,850,1000,1003,1004,1006],{},"Keys are dotted paths (",[18,998,999],{},"'user.email'",[18,1001,1002],{},"'items.0.qty'","). A field's\nvalue is either a single entry or an array — array entries each\nproduce their own ",[18,1005,798],{},", so a single field can carry\nmultiple distinct failures with their own codes.",[14,1008,1009,1010,850,1013,850,1016,1019,1020,1022],{},"Pick a prefix for your codes (",[18,1011,1012],{},"api:",[18,1014,1015],{},"auth:",[18,1017,1018],{},"myapp:",") and stay\nconsistent so consumer error-rendering UIs can switch on ",[18,1021,18],{},".",[14,1024,1025,1026,1029,1030,1032,1033,1035,1036,1022],{},"Legacy string entries (",[18,1027,1028],{},"{ email: 'taken' }","), entries missing\n",[18,1031,18],{},", and entries with non-string ",[18,1034,18],{}," are rejected as\n",[18,1037,1038],{},"{ ok: false, rejected }",[35,1040,1042,1043],{"id":1041},"branching-on-code","Branching on ",[18,1044,18],{},[40,1046,1048],{"className":628,"code":1047,"language":630,"meta":45,"style":45},"import { AttaformErrorCode } from 'attaform'\n\nfor (const err of form.errors.email ?? []) {\n  if (err.code === 'api:duplicate-email') {\n    \u002F\u002F server-side uniqueness failure\n  } else if (err.code === AttaformErrorCode.NoValueSupplied) {\n    \u002F\u002F user opened the form and didn't fill the field\n  } else if (err.code.startsWith('zod:')) {\n    \u002F\u002F schema-level validation failure\n  }\n}\n",[18,1049,1050,1062,1066,1090,1105,1110,1127,1132,1154,1159,1164],{"__ignoreMap":45},[49,1051,1052,1055,1058,1060],{"class":51,"line":52},[49,1053,1054],{"class":83},"import",[49,1056,1057],{"class":55}," { AttaformErrorCode } ",[49,1059,90],{"class":83},[49,1061,93],{"class":73},[49,1063,1064],{"class":51,"line":80},[49,1065,113],{"emptyLinePlaceholder":112},[49,1067,1068,1071,1073,1075,1078,1081,1084,1087],{"class":51,"line":96},[49,1069,1070],{"class":83},"for",[49,1072,233],{"class":55},[49,1074,727],{"class":83},[49,1076,1077],{"class":122}," err",[49,1079,1080],{"class":83}," of",[49,1082,1083],{"class":55}," form.errors.email ",[49,1085,1086],{"class":83},"??",[49,1088,1089],{"class":55}," []) {\n",[49,1091,1092,1095,1098,1100,1103],{"class":51,"line":109},[49,1093,1094],{"class":83},"  if",[49,1096,1097],{"class":55}," (err.code ",[49,1099,312],{"class":83},[49,1101,1102],{"class":73}," 'api:duplicate-email'",[49,1104,300],{"class":55},[49,1106,1107],{"class":51,"line":116},[49,1108,1109],{"class":372},"    \u002F\u002F server-side uniqueness failure\n",[49,1111,1112,1115,1117,1120,1122,1124],{"class":51,"line":138},[49,1113,1114],{"class":55},"  } ",[49,1116,760],{"class":83},[49,1118,1119],{"class":83}," if",[49,1121,1097],{"class":55},[49,1123,312],{"class":83},[49,1125,1126],{"class":55}," AttaformErrorCode.NoValueSupplied) {\n",[49,1128,1129],{"class":51,"line":150},[49,1130,1131],{"class":372},"    \u002F\u002F user opened the form and didn't fill the field\n",[49,1133,1134,1136,1138,1140,1143,1146,1148,1151],{"class":51,"line":174},[49,1135,1114],{"class":55},[49,1137,760],{"class":83},[49,1139,1119],{"class":83},[49,1141,1142],{"class":55}," (err.code.",[49,1144,1145],{"class":63},"startsWith",[49,1147,165],{"class":55},[49,1149,1150],{"class":73},"'zod:'",[49,1152,1153],{"class":55},")) {\n",[49,1155,1156],{"class":51,"line":180},[49,1157,1158],{"class":372},"    \u002F\u002F schema-level validation failure\n",[49,1160,1161],{"class":51,"line":185},[49,1162,1163],{"class":55},"  }\n",[49,1165,1166],{"class":51,"line":207},[49,1167,690],{"class":55},[14,1169,1170,1173,1174,1177,1178,1181,1182,1184,1185,1187,1188,1190],{},[18,1171,1172],{},"AttaformErrorCode"," exports the library-internal codes; the ",[18,1175,1176],{},"zod:"," prefix\nis computed inline from ",[18,1179,1180],{},"issue.code","; consumer codes (",[18,1183,1012],{},",\n",[18,1186,1015],{},", etc.) come from the wire payload or direct\n",[18,1189,28],{}," calls.",[35,1192,1194],{"id":1193},"pairing-with-focus-on-error","Pairing with focus-on-error",[14,1196,1197],{},"A 422 with no visible focus is invisible to screen-reader users and\neasy to miss for sighted users scrolled past the error. Hydrate",[692,1199,1200],{},[695,1201,1202],{},"focus in the same block:",[40,1204,1206],{"className":628,"code":1205,"language":630,"meta":45,"style":45},"const onSubmit = form.handleSubmit(async (values) => {\n  try {\n    await $fetch('\u002Fapi\u002Fsignup', { method: 'POST', body: values })\n  } catch (err: any) {\n    if (err.statusCode === 422) {\n      const result = parseApiErrors(err.data, { formKey: form.key })\n      if (result.ok) {\n        form.setFieldErrors(result.errors)\n        form.focusFirstError({ preventScroll: true })\n        form.scrollToFirstError({ block: 'center', behavior: 'smooth' })\n      }\n    }\n  }\n})\n",[18,1207,1208,1234,1241,1258,1274,1287,1300,1306,1315,1330,1351,1355,1359,1363],{"__ignoreMap":45},[49,1209,1210,1212,1214,1216,1218,1220,1222,1224,1226,1228,1230,1232],{"class":51,"line":52},[49,1211,727],{"class":83},[49,1213,217],{"class":122},[49,1215,126],{"class":83},[49,1217,222],{"class":55},[49,1219,225],{"class":63},[49,1221,165],{"class":55},[49,1223,230],{"class":83},[49,1225,233],{"class":55},[49,1227,237],{"class":236},[49,1229,240],{"class":55},[49,1231,243],{"class":83},[49,1233,246],{"class":55},[49,1235,1236,1239],{"class":51,"line":80},[49,1237,1238],{"class":83},"  try",[49,1240,246],{"class":55},[49,1242,1243,1246,1248,1250,1252,1254,1256],{"class":51,"line":96},[49,1244,1245],{"class":83},"    await",[49,1247,263],{"class":63},[49,1249,165],{"class":55},[49,1251,268],{"class":73},[49,1253,271],{"class":55},[49,1255,274],{"class":73},[49,1257,277],{"class":55},[49,1259,1260,1262,1264,1266,1268,1270,1272],{"class":51,"line":109},[49,1261,1114],{"class":55},[49,1263,286],{"class":83},[49,1265,233],{"class":55},[49,1267,291],{"class":236},[49,1269,294],{"class":83},[49,1271,297],{"class":122},[49,1273,300],{"class":55},[49,1275,1276,1279,1281,1283,1285],{"class":51,"line":116},[49,1277,1278],{"class":83},"    if",[49,1280,309],{"class":55},[49,1282,312],{"class":83},[49,1284,315],{"class":122},[49,1286,300],{"class":55},[49,1288,1289,1292,1294,1296,1298],{"class":51,"line":138},[49,1290,1291],{"class":83},"      const",[49,1293,326],{"class":122},[49,1295,126],{"class":83},[49,1297,331],{"class":63},[49,1299,334],{"class":55},[49,1301,1302,1304],{"class":51,"line":150},[49,1303,306],{"class":83},[49,1305,743],{"class":55},[49,1307,1308,1311,1313],{"class":51,"line":174},[49,1309,1310],{"class":55},"        form.",[49,1312,28],{"class":63},[49,1314,348],{"class":55},[49,1316,1317,1319,1322,1325,1328],{"class":51,"line":180},[49,1318,1310],{"class":55},[49,1320,1321],{"class":63},"focusFirstError",[49,1323,1324],{"class":55},"({ preventScroll: ",[49,1326,1327],{"class":122},"true",[49,1329,204],{"class":55},[49,1331,1332,1334,1337,1340,1343,1346,1349],{"class":51,"line":185},[49,1333,1310],{"class":55},[49,1335,1336],{"class":63},"scrollToFirstError",[49,1338,1339],{"class":55},"({ block: ",[49,1341,1342],{"class":73},"'center'",[49,1344,1345],{"class":55},", behavior: ",[49,1347,1348],{"class":73},"'smooth'",[49,1350,204],{"class":55},[49,1352,1353],{"class":51,"line":207},[49,1354,360],{"class":55},[49,1356,1357],{"class":51,"line":212},[49,1358,379],{"class":55},[49,1360,1361],{"class":51,"line":249},[49,1362,1163],{"class":55},[49,1364,1365],{"class":51,"line":257},[49,1366,1367],{"class":55},"})\n",[35,1369,1371],{"id":1370},"mixing-server-client-errors","Mixing server + client errors",[14,1373,1374],{},"To replace one field's error without wiping the rest, skip the\nparser and construct the entries directly:",[40,1376,1378],{"className":628,"code":1377,"language":630,"meta":45,"style":45},"if (err.statusCode === 422) {\n  form.clearFieldErrors('coupon')\n  \u002F\u002F Wire entries are { message, code } — the field's value can be\n  \u002F\u002F a single entry or an array. Normalise so .map() handles both.\n  const raw = err.data.coupon\n  const entries: { message: string; code: string }[] = Array.isArray(raw) ? raw : raw ? [raw] : []\n  form.addFieldErrors(\n    entries.map((entry) => ({\n      path: ['coupon'],\n      message: entry.message,\n      code: entry.code,\n      formKey: form.key,\n    }))\n  )\n}\n",[18,1379,1380,1392,1407,1412,1417,1429,1491,1500,1521,1531,1536,1541,1546,1551,1556],{"__ignoreMap":45},[49,1381,1382,1384,1386,1388,1390],{"class":51,"line":52},[49,1383,740],{"class":83},[49,1385,309],{"class":55},[49,1387,312],{"class":83},[49,1389,315],{"class":122},[49,1391,300],{"class":55},[49,1393,1394,1396,1399,1401,1404],{"class":51,"line":80},[49,1395,748],{"class":55},[49,1397,1398],{"class":63},"clearFieldErrors",[49,1400,165],{"class":55},[49,1402,1403],{"class":73},"'coupon'",[49,1405,1406],{"class":55},")\n",[49,1408,1409],{"class":51,"line":96},[49,1410,1411],{"class":372},"  \u002F\u002F Wire entries are { message, code } — the field's value can be\n",[49,1413,1414],{"class":51,"line":109},[49,1415,1416],{"class":372},"  \u002F\u002F a single entry or an array. Normalise so .map() handles both.\n",[49,1418,1419,1421,1424,1426],{"class":51,"line":116},[49,1420,119],{"class":83},[49,1422,1423],{"class":122}," raw",[49,1425,126],{"class":83},[49,1427,1428],{"class":55}," err.data.coupon\n",[49,1430,1431,1433,1436,1438,1441,1443,1445,1448,1451,1453,1455,1457,1460,1462,1465,1468,1471,1474,1477,1479,1481,1483,1486,1488],{"class":51,"line":138},[49,1432,119],{"class":83},[49,1434,1435],{"class":122}," entries",[49,1437,294],{"class":83},[49,1439,1440],{"class":55}," { ",[49,1442,841],{"class":236},[49,1444,294],{"class":83},[49,1446,1447],{"class":122}," string",[49,1449,1450],{"class":55},"; ",[49,1452,18],{"class":236},[49,1454,294],{"class":83},[49,1456,1447],{"class":122},[49,1458,1459],{"class":55}," }[] ",[49,1461,70],{"class":83},[49,1463,1464],{"class":55}," Array.",[49,1466,1467],{"class":63},"isArray",[49,1469,1470],{"class":55},"(raw) ",[49,1472,1473],{"class":83},"?",[49,1475,1476],{"class":55}," raw ",[49,1478,294],{"class":83},[49,1480,1476],{"class":55},[49,1482,1473],{"class":83},[49,1484,1485],{"class":55}," [raw] ",[49,1487,294],{"class":83},[49,1489,1490],{"class":55}," []\n",[49,1492,1493,1495,1497],{"class":51,"line":150},[49,1494,748],{"class":55},[49,1496,32],{"class":63},[49,1498,1499],{"class":55},"(\n",[49,1501,1502,1505,1508,1511,1514,1516,1518],{"class":51,"line":174},[49,1503,1504],{"class":55},"    entries.",[49,1506,1507],{"class":63},"map",[49,1509,1510],{"class":55},"((",[49,1512,1513],{"class":236},"entry",[49,1515,240],{"class":55},[49,1517,243],{"class":83},[49,1519,1520],{"class":55}," ({\n",[49,1522,1523,1526,1528],{"class":51,"line":180},[49,1524,1525],{"class":55},"      path: [",[49,1527,1403],{"class":73},[49,1529,1530],{"class":55},"],\n",[49,1532,1533],{"class":51,"line":185},[49,1534,1535],{"class":55},"      message: entry.message,\n",[49,1537,1538],{"class":51,"line":207},[49,1539,1540],{"class":55},"      code: entry.code,\n",[49,1542,1543],{"class":51,"line":212},[49,1544,1545],{"class":55},"      formKey: form.key,\n",[49,1547,1548],{"class":51,"line":249},[49,1549,1550],{"class":55},"    }))\n",[49,1552,1553],{"class":51,"line":257},[49,1554,1555],{"class":55},"  )\n",[49,1557,1558],{"class":51,"line":280},[49,1559,690],{"class":55},[14,1561,1562,1564,1565,1567,1568,1570,1571,1573],{},[18,1563,24],{}," + ",[18,1566,28],{}," is the right default for\n\"replace everything from this payload\". ",[18,1569,32],{}," +\n",[18,1572,1398],{}," are for finer control. Both write to the same\nuser-error store; merging is structural.",[35,1575,1577],{"id":1576},"non-field-errors","Non-field errors",[14,1579,1580,1581,1584,1585,294],{},"Some server errors aren't tied to a field — rate limits, provider\noutages. They belong in ",[18,1582,1583],{},"meta.submitError",", not ",[18,1586,20],{},[40,1588,1590],{"className":628,"code":1589,"language":630,"meta":45,"style":45},"const onSubmit = form.handleSubmit(async (values) => {\n  const res = await $fetch('\u002Fapi\u002Fsignup', { method: 'POST', body: values })\n  if (!res.ok) {\n    throw new Error(res.error ?? 'Something went wrong. Try again shortly.')\n  }\n})\n",[18,1591,1592,1618,1642,1654,1675,1679],{"__ignoreMap":45},[49,1593,1594,1596,1598,1600,1602,1604,1606,1608,1610,1612,1614,1616],{"class":51,"line":52},[49,1595,727],{"class":83},[49,1597,217],{"class":122},[49,1599,126],{"class":83},[49,1601,222],{"class":55},[49,1603,225],{"class":63},[49,1605,165],{"class":55},[49,1607,230],{"class":83},[49,1609,233],{"class":55},[49,1611,237],{"class":236},[49,1613,240],{"class":55},[49,1615,243],{"class":83},[49,1617,246],{"class":55},[49,1619,1620,1622,1625,1627,1630,1632,1634,1636,1638,1640],{"class":51,"line":80},[49,1621,119],{"class":83},[49,1623,1624],{"class":122}," res",[49,1626,126],{"class":83},[49,1628,1629],{"class":83}," await",[49,1631,263],{"class":63},[49,1633,165],{"class":55},[49,1635,268],{"class":73},[49,1637,271],{"class":55},[49,1639,274],{"class":73},[49,1641,277],{"class":55},[49,1643,1644,1646,1648,1651],{"class":51,"line":96},[49,1645,1094],{"class":83},[49,1647,233],{"class":55},[49,1649,1650],{"class":83},"!",[49,1652,1653],{"class":55},"res.ok) {\n",[49,1655,1656,1659,1662,1665,1668,1670,1673],{"class":51,"line":109},[49,1657,1658],{"class":83},"    throw",[49,1660,1661],{"class":83}," new",[49,1663,1664],{"class":63}," Error",[49,1666,1667],{"class":55},"(res.error ",[49,1669,1086],{"class":83},[49,1671,1672],{"class":73}," 'Something went wrong. Try again shortly.'",[49,1674,1406],{"class":55},[49,1676,1677],{"class":51,"line":116},[49,1678,1163],{"class":55},[49,1680,1681],{"class":51,"line":138},[49,1682,1367],{"class":55},[40,1684,1686],{"className":42,"code":1685,"language":44,"meta":45,"style":45},"\u003Ctemplate>\n  \u003Cp v-if=\"form.meta.submitError\" role=\"alert\">\n    {{ (form.meta.submitError as Error).message }}\n  \u003C\u002Fp>\n\u003C\u002Ftemplate>\n",[18,1687,1688,1696,1719,1724,1732],{"__ignoreMap":45},[49,1689,1690,1692,1694],{"class":51,"line":52},[49,1691,56],{"class":55},[49,1693,407],{"class":59},[49,1695,77],{"class":55},[49,1697,1698,1700,1702,1704,1706,1709,1712,1714,1717],{"class":51,"line":80},[49,1699,415],{"class":55},[49,1701,14],{"class":59},[49,1703,459],{"class":63},[49,1705,70],{"class":55},[49,1707,1708],{"class":73},"\"form.meta.submitError\"",[49,1710,1711],{"class":63}," role",[49,1713,70],{"class":55},[49,1715,1716],{"class":73},"\"alert\"",[49,1718,77],{"class":55},[49,1720,1721],{"class":51,"line":96},[49,1722,1723],{"class":55},"    {{ (form.meta.submitError as Error).message }}\n",[49,1725,1726,1728,1730],{"class":51,"line":109},[49,1727,576],{"class":55},[49,1729,14],{"class":59},[49,1731,77],{"class":55},[49,1733,1734,1736,1738],{"class":51,"line":116},[49,1735,390],{"class":55},[49,1737,407],{"class":59},[49,1739,77],{"class":55},[35,1741,1743],{"id":1742},"untrusted-payloads","Untrusted payloads",[14,1745,1746],{},"If your API response is first-party, defaults are fine. If the\npayload might cross an untrusted gateway or a federated API, three\nthings to know:",[14,1748,1749,1752,1753,1755],{},[596,1750,1751],{},"1. Entry-count \u002F path-depth caps."," ",[18,1754,24],{}," accepts\noptional caps in its options bag:",[40,1757,1759],{"className":628,"code":1758,"language":630,"meta":45,"style":45},"const result = parseApiErrors(response, {\n  formKey: form.key,\n  maxEntries: 50,\n  maxPathDepth: 8,\n})\n",[18,1760,1761,1774,1779,1789,1798],{"__ignoreMap":45},[49,1762,1763,1765,1767,1769,1771],{"class":51,"line":52},[49,1764,727],{"class":83},[49,1766,326],{"class":122},[49,1768,126],{"class":83},[49,1770,331],{"class":63},[49,1772,1773],{"class":55},"(response, {\n",[49,1775,1776],{"class":51,"line":80},[49,1777,1778],{"class":55},"  formKey: form.key,\n",[49,1780,1781,1784,1787],{"class":51,"line":96},[49,1782,1783],{"class":55},"  maxEntries: ",[49,1785,1786],{"class":122},"50",[49,1788,1184],{"class":55},[49,1790,1791,1794,1796],{"class":51,"line":109},[49,1792,1793],{"class":55},"  maxPathDepth: ",[49,1795,168],{"class":122},[49,1797,1184],{"class":55},[49,1799,1800],{"class":51,"line":116},[49,1801,1367],{"class":55},[14,1803,1804,1805,850,1808,1811,1812,1814],{},"Defaults are ",[18,1806,1807],{},"maxEntries: 1000",[18,1809,1810],{},"maxPathDepth: 32",". Over-budget\npayloads are rejected wholesale (the result is ",[18,1813,1038],{},"); over-depth individual keys are dropped while the rest\nof the payload still applies. Tighten the caps for pass-through\ncode.",[14,1816,1817,1820],{},[596,1818,1819],{},"2. Message content shows in your UI."," Vue's text binding escapes\noutput, so XSS is not a concern — but an attacker-controlled\nmessage can display misleading copy (\"your account is suspended;\nclick here\"). Validate the length and allowed characters before\nbinding.",[14,1822,1823,1826,1827,1830],{},[596,1824,1825],{},"3. Unknown paths accept quietly."," An error pushed to\n",[18,1828,1829],{},"users.0.adminPasswordHash"," is harmless (no field renders it) but\ncan confuse error-surfacing logic. Pre-parse the payload with a Zod\nschema to reject anything unexpected:",[40,1832,1834],{"className":628,"code":1833,"language":630,"meta":45,"style":45},"const Entry = z.object({ message: z.string(), code: z.string() })\nconst ErrorPayload = z.object({\n  error: z.object({\n    details: z.record(z.string(), z.union([Entry, z.array(Entry)])),\n  }),\n})\n\nconst parsed = ErrorPayload.safeParse(response)\nif (parsed.success) {\n  const result = parseApiErrors(parsed.data, {\n    formKey: form.key,\n    maxEntries: 200,\n  })\n  if (result.ok) form.setFieldErrors(result.errors)\n}\n",[18,1835,1836,1862,1877,1886,1914,1919,1923,1927,1945,1952,1965,1970,1980,1984,1994],{"__ignoreMap":45},[49,1837,1838,1840,1843,1845,1847,1849,1852,1854,1857,1859],{"class":51,"line":52},[49,1839,727],{"class":83},[49,1841,1842],{"class":122}," Entry",[49,1844,126],{"class":83},[49,1846,129],{"class":55},[49,1848,132],{"class":63},[49,1850,1851],{"class":55},"({ message: z.",[49,1853,156],{"class":63},[49,1855,1856],{"class":55},"(), code: z.",[49,1858,156],{"class":63},[49,1860,1861],{"class":55},"() })\n",[49,1863,1864,1866,1869,1871,1873,1875],{"class":51,"line":80},[49,1865,727],{"class":83},[49,1867,1868],{"class":122}," ErrorPayload",[49,1870,126],{"class":83},[49,1872,129],{"class":55},[49,1874,132],{"class":63},[49,1876,135],{"class":55},[49,1878,1879,1882,1884],{"class":51,"line":96},[49,1880,1881],{"class":55},"  error: z.",[49,1883,132],{"class":63},[49,1885,135],{"class":55},[49,1887,1888,1891,1894,1897,1899,1902,1905,1908,1911],{"class":51,"line":109},[49,1889,1890],{"class":55},"    details: z.",[49,1892,1893],{"class":63},"record",[49,1895,1896],{"class":55},"(z.",[49,1898,156],{"class":63},[49,1900,1901],{"class":55},"(), z.",[49,1903,1904],{"class":63},"union",[49,1906,1907],{"class":55},"([Entry, z.",[49,1909,1910],{"class":63},"array",[49,1912,1913],{"class":55},"(Entry)])),\n",[49,1915,1916],{"class":51,"line":116},[49,1917,1918],{"class":55},"  }),\n",[49,1920,1921],{"class":51,"line":138},[49,1922,1367],{"class":55},[49,1924,1925],{"class":51,"line":150},[49,1926,113],{"emptyLinePlaceholder":112},[49,1928,1929,1931,1934,1936,1939,1942],{"class":51,"line":174},[49,1930,727],{"class":83},[49,1932,1933],{"class":122}," parsed",[49,1935,126],{"class":83},[49,1937,1938],{"class":55}," ErrorPayload.",[49,1940,1941],{"class":63},"safeParse",[49,1943,1944],{"class":55},"(response)\n",[49,1946,1947,1949],{"class":51,"line":180},[49,1948,740],{"class":83},[49,1950,1951],{"class":55}," (parsed.success) {\n",[49,1953,1954,1956,1958,1960,1962],{"class":51,"line":185},[49,1955,119],{"class":83},[49,1957,326],{"class":122},[49,1959,126],{"class":83},[49,1961,331],{"class":63},[49,1963,1964],{"class":55},"(parsed.data, {\n",[49,1966,1967],{"class":51,"line":207},[49,1968,1969],{"class":55},"    formKey: form.key,\n",[49,1971,1972,1975,1978],{"class":51,"line":212},[49,1973,1974],{"class":55},"    maxEntries: ",[49,1976,1977],{"class":122},"200",[49,1979,1184],{"class":55},[49,1981,1982],{"class":51,"line":249},[49,1983,177],{"class":55},[49,1985,1986,1988,1990,1992],{"class":51,"line":257},[49,1987,1094],{"class":83},[49,1989,343],{"class":55},[49,1991,28],{"class":63},[49,1993,348],{"class":55},[49,1995,1996],{"class":51,"line":280},[49,1997,690],{"class":55},[1999,2000,2001],"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 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);}",{"title":45,"searchDepth":80,"depth":80,"links":2003},[2004,2005,2006,2007,2009,2010,2011,2012],{"id":37,"depth":80,"text":38},{"id":619,"depth":80,"text":620},{"id":785,"depth":80,"text":786},{"id":1041,"depth":80,"text":2008},"Branching on code",{"id":1193,"depth":80,"text":1194},{"id":1370,"depth":80,"text":1371},{"id":1576,"depth":80,"text":1577},{"id":1742,"depth":80,"text":1743},"Server-side rules the client doesn't know — \"email already taken\",\n\"coupon expired\", \"we couldn't reach the payment provider\" — surface\nas errors via a two-step pattern: parse the payload with\nparseApiErrors, write the result with setFieldErrors (or\naddFieldErrors).","md",{},"\u002Fdocs\u002Frecipes\u002Fserver-errors",{"title":5,"description":2013},"docs\u002Frecipes\u002Fserver-errors","aJWG0ylP4VEpOJk3IrRLl0tOvx-Ok42zCl8Hy9pOUN8",1777934136661]