{"record":{"id":"8b9dc5725a9311f2","repo":"withastro/astro","slug":"bad-request-8b9dc5","errorCode":"BAD_REQUEST","errorMessage":"Failed to validate: ${JSON.stringify(issues, null, 2)}","messagePattern":"Failed to validate: (.+?)","errorType":"error_code","errorClass":"ActionInputError","httpStatus":400,"severity":"error","filePath":"packages/astro/src/actions/runtime/client.ts","lineNumber":140,"sourceCode":"\t\t'issues' in error &&\n\t\tArray.isArray(error.issues)\n\t);\n}\n\nexport class ActionInputError<T extends ErrorInferenceObject> extends ActionError {\n\ttype = 'AstroActionInputError';\n\n\t// We don't expose all ZodError properties.\n\t// Not all properties will serialize from server to client,\n\t// and we don't want to import the full ZodError object into the client.\n\n\tissues: z.$ZodIssue[];\n\tfields: { [P in keyof T]?: string[] | undefined };\n\n\tconstructor(issues: z.$ZodIssue[]) {\n\t\tsuper({\n\t\t\tmessage: `Failed to validate: ${JSON.stringify(issues, null, 2)}`,\n\t\t\tcode: 'BAD_REQUEST',\n\t\t});\n\t\tthis.issues = issues;\n\t\tthis.fields = {};\n\t\tfor (const issue of issues) {\n\t\t\tif (issue.path.length > 0) {\n\t\t\t\tconst key = issue.path[0].toString() as keyof typeof this.fields;\n\t\t\t\tthis.fields[key] ??= [];\n\t\t\t\tthis.fields[key]?.push(issue.message);\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport function deserializeActionResult(res: SerializedActionResult): SafeResult<any, any> {\n\tif (res.type === 'error') {\n\t\tlet json;\n\t\ttry {\n\t\t\tjson = JSON.parse(res.body);","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/withastro/astro/blob/52e6c34790cc8ac4e69e6135ace06049867e5c4a/packages/astro/src/actions/runtime/client.ts#L122-L158","documentation":"`AstroActionInputError` is the client-side error produced when a server action call fails input validation. The server's Zod issues are serialized back and this class re-throws them with `code: 'BAD_REQUEST'`; the message embeds the JSON of the issues, and the `fields` property groups issue messages by first path key for convenient form display.","triggerScenarios":"Calling an action from the client (e.g. in a `<script>` via `actions.user.create(...)`) with input that violates the action's Zod schema: wrong type, missing required field, failing string constraints like email/min length.","commonSituations":"Form submissions where a field is empty or malformed; schema and UI drifting apart (schema gained a required field the form doesn't send); coercion surprises — sending a number as a string when the schema expects `z.number()`.","solutions":["Inspect `error.fields` (or the JSON in the message) to see exactly which field(s) and constraints failed","Fix the payload to satisfy the schema, or adjust the schema (add `.optional()`, `z.coerce.number()`, etc.)","Validate client-side before calling the action to give faster feedback, treating the server error as the backstop"],"exampleFix":"// schema expects z.object({ email: z.string().email() })\n// before\nconst result = await actions.newsletter.subscribe({ email: 'not-an-email' });\n\n// after\nconst result = await actions.newsletter.subscribe({ email: 'user@example.com' });","handlingStrategy":"validation","validationCode":"import { z } from 'astro/zod';\nconst schema = z.object({ email: z.string().email(), age: z.coerce.number().int().min(0) });\nconst check = schema.safeParse(draft);\nif (!check.success) {\n  setFieldErrors(groupIssuesByField(check.error.issues));\n} else {\n  await actions.user.create(check.data);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await actions.user.create(input);\n} catch (e) {\n  if (e instanceof ActionError && e.type === 'AstroActionInputError') {\n    // e.fields maps field name -> string[] of messages\n    showFormErrors(e.fields);\n    return;\n  }\n  throw e;\n}","preventionTips":["Mirror the action's Zod schema for client-side pre-validation","Use z.coerce for form inputs that arrive as strings","Render error.fields next to the corresponding inputs instead of dumping raw JSON"],"tags":["actions","zod","validation","client"],"backgroundTag":"schema-validation-failed","analyzedSha":"52e6c34790cc8ac4e69e6135ace06049867e5c4a","analyzedAt":"2026-08-18T18:48:03.901Z","contentChangedAt":"2026-08-18T18:48:03.901Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}