withastro/astro · error · ActionInputError
BAD_REQUEST
BAD_REQUEST
Error message
Failed to validate: ${JSON.stringify(issues, null, 2)} What it means
After converting FormData against the action's zod input schema (parseFormInput), validation failed. The handler throws ActionInputError carrying the zod issues, surfaced to the caller as ActionError code BAD_REQUEST (400).
Source
Thrown at packages/astro/src/actions/runtime/server.ts:91
function getFormServerHandler<TOutput, TInputSchema extends z.$ZodType>(
handler: ActionHandler<TInputSchema, TOutput>,
inputSchema?: TInputSchema,
) {
return async (unparsedInput: unknown, context: ActionAPIContext): Promise<Awaited<TOutput>> => {
if (!(unparsedInput instanceof FormData)) {
throw new ActionError({
code: 'UNSUPPORTED_MEDIA_TYPE',
message: 'This action only accepts FormData.',
});
}
if (!inputSchema) return await handler(unparsedInput, context);
const parsed = await parseFormInput(inputSchema, unparsedInput);
if (!parsed.success) {
throw new ActionInputError(parsed.error.issues);
}
return await handler(parsed.data, context);
};
}
async function parseFormInput(inputSchema: z.$ZodType, unparsedInput: FormData) {
const baseSchema = unwrapBaseZ4ObjectSchema(inputSchema, unparsedInput);
const input =
baseSchema instanceof z.$ZodObject
? formDataToObject(unparsedInput, baseSchema)
: unparsedInput;
const parsed = await z.safeParseAsync(inputSchema, input);
return parsed;
}
function getJsonServerHandler<TOutput, TInputSchema extends z.$ZodType>(
handler: ActionHandler<TInputSchema, TOutput>,View on GitHub (pinned to d081033d5f)
Solutions
- Inspect the error with isInputError(error) and read error.fields to display per-field messages.
- Align the form input names with the zod schema keys (including nested prefixes).
- Add matching client-side validation so invalid forms are caught before submission.
Example fix
// before - schema wants a number age, form sends string and is missing it
const input = z.object({ name: z.string(), age: z.number() });
// after - use coercion + optional handling, and check error.fields on the client
const input = z.object({
name: z.string().min(1),
age: z.coerce.number().int().nonnegative(),
});
// client
const { data, error } = await actions.signup.orThrow(fd);
if (isInputError(error)) showError(error.fields); Defensive patterns
Strategy: try-catch
Validate before calling
// Validate form input against the same zod schema on the client before calling. const parsed = subscribeSchema.safeParse(Object.fromEntries(new FormData(formEl))); if (!parsed.success) showFieldErrors(parsed.error.issues);
Type guard
// On the result, narrow to an input error to read field issues.
function isInputError(e: unknown): e is { fields: Record<string, string[]> } {
return e instanceof ActionError && (e as any).fields !== undefined;
} Try / catch
const { data, error } = await actions.signup(fd);
if (isInputError(error)) {
for (const [field, msgs] of Object.entries(error.fields)) showFieldError(field, msgs.join(', '));
} Prevention
- Reuse the action's zod schema on the client for pre-validation.
- Keep HTML input names aligned with schema keys.
- Always handle isInputError to render field-level messages.
When it happens
Trigger: A form submission whose fields do not satisfy the schema: missing required fields, wrong types, failed refinements, or field names that do not match schema keys.
Common situations: User submits an incomplete form; HTML input names differ from zod keys; type mismatch (string where number expected); file field not allowed by schema.
Related errors
- UNSUPPORTED_MEDIA_TYPE
- Expected handler for action ${pathKeys.join('.')} to be a fu
- [astro:actions] `defineAction()` unexpectedly used on the cl
- [astro:actions] `getActionContext()` unexpectedly used on th
- BAD_REQUEST
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/49fc73ba189a24d2.
Report an issue: GitHub.