withastro/astro · error · ActionInputError
BAD_REQUEST
BAD_REQUEST
Error message
Failed to validate: ${JSON.stringify(issues, null, 2)} What it means
`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.
Source
Thrown at packages/astro/src/actions/runtime/client.ts:140
'issues' in error &&
Array.isArray(error.issues)
);
}
export class ActionInputError<T extends ErrorInferenceObject> extends ActionError {
type = 'AstroActionInputError';
// We don't expose all ZodError properties.
// Not all properties will serialize from server to client,
// and we don't want to import the full ZodError object into the client.
issues: z.$ZodIssue[];
fields: { [P in keyof T]?: string[] | undefined };
constructor(issues: z.$ZodIssue[]) {
super({
message: `Failed to validate: ${JSON.stringify(issues, null, 2)}`,
code: 'BAD_REQUEST',
});
this.issues = issues;
this.fields = {};
for (const issue of issues) {
if (issue.path.length > 0) {
const key = issue.path[0].toString() as keyof typeof this.fields;
this.fields[key] ??= [];
this.fields[key]?.push(issue.message);
}
}
}
}
export function deserializeActionResult(res: SerializedActionResult): SafeResult<any, any> {
if (res.type === 'error') {
let json;
try {
json = JSON.parse(res.body);View on GitHub (pinned to 52e6c34790)
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
Example fix
// schema expects z.object({ email: z.string().email() })
// before
const result = await actions.newsletter.subscribe({ email: 'not-an-email' });
// after
const result = await actions.newsletter.subscribe({ email: 'user@example.com' }); Defensive patterns
Strategy: validation
Validate before calling
import { z } from 'astro/zod';
const schema = z.object({ email: z.string().email(), age: z.coerce.number().int().min(0) });
const check = schema.safeParse(draft);
if (!check.success) {
setFieldErrors(groupIssuesByField(check.error.issues));
} else {
await actions.user.create(check.data);
} Try / catch
try {
await actions.user.create(input);
} catch (e) {
if (e instanceof ActionError && e.type === 'AstroActionInputError') {
// e.fields maps field name -> string[] of messages
showFormErrors(e.fields);
return;
}
throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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()`.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- ${issue.path.join('.')} ${issue.message + '.'}
- BAD_REQUEST
- ContentLoaderReturnsInvalidId
- Request body exceeds the configured limit of ${limit} bytes
- InvalidGetStaticPathsReturn
AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18).
Data as JSON: /api/errors/8b9dc5725a9311f2.
Report an issue: GitHub.