API Routes and Server ActionsLesson 3.4
How to validate and sanitize data in Next.js Server Actions
Zod validation, schema parsing, safeParse, error handling in actions, type-safe FormData, input sanitization patterns
Never Trust FormData
FormData values are always strings. Users can send anything. Validate on the server before touching your database. Zod is the standard tool for this.
npm install zod'use server'
import { z } from 'zod'
const PostSchema = z.object({
title: z.string().min(1, 'Title required').max(100),
content: z.string().min(10, 'Too short'),
published: z.coerce.boolean().default(false),
})
export async function createPost(
prevState: { errors: Record<string, string[]> | null },
formData: FormData
) {
const raw = {
title: formData.get('title'),
content: formData.get('content'),
published: formData.get('published'),
}
const result = PostSchema.safeParse(raw)
if (!result.success) {
return { errors: result.error.flatten().fieldErrors }
}
await db.post.create({ data: result.data })
revalidatePath('/blog')
return { errors: null }
}Displaying Field Errors
// In the Client Component:
{state.errors?.title && (
<span className="text-red-500">{state.errors.title[0]}</span>
)}Use safeParse (not parse) to avoid throwing. safeParse returns a result object you can inspect. flatten().fieldErrors gives you field-level error messages as arrays, perfect for displaying next to each input.
