Safe Action Validation Errors

next-safe-action/skills/skills/safe-action-validation-errors

作者 next-safe-actiona2605bd2e84321245cba8f5718c144a6e4a5fa47无许可证收录于 2026年10月9日更新于 2026年10月9日

Use when working with validation errors -- returnValidationErrors, formatted vs flattened shapes, custom validation error shapes, throwValidationErrors, or displaying field-level and form-level errors

AI 生成的概览

说明 next-safe-action 的验证错误结构与辅助函数,用于返回并显示字段级和表单级错误。

功能
说明 next-safe-action 如何通过 schema 验证和手动检查产生验证错误,涵盖带嵌套 _errors 数组的默认格式化结构,以及包含 fieldErrors 和 formErrors 的扁平化结构。它展示 returnValidationErrors 如何抛出 ActionServerValidationError 并最终体现为 result.validationErrors,包括根级表单错误,并给出渲染字段错误和表单错误的 React 示例。另有两份配套文档分别介绍自定义错误结构和格式化与扁平化输出。
适用场景
适用于处理 next-safe-action 验证错误的场景,包括 returnValidationErrors、格式化或扁平化错误结构、自定义验证错误结构,以及在表单中渲染字段级和表单级错误。
运行要求
不含脚本,仅为说明文档。假定使用 next-safe-action 项目,并搭配 Zod 等 schema 库,显示示例需要 React 前端。

next-safe-action Validation Errors

Two Sources of Validation Errors

  1. Schema validation — automatic when input doesn't match .inputSchema()
  2. Manual validation — via returnValidationErrors() in server code (e.g., "email already taken")

Both produce the same error structure on the client.

Default Error Shape (Formatted)

Mirrors the schema structure with _errors arrays at each level:

ts
// For schema: z.object({ email: z.string().email(), address: z.object({ city: z.string() }) }){  _errors: ["Form-level error"],                    // root errors  email: { _errors: ["Invalid email address"] },    // field errors  address: {    _errors: ["Address section error"],    city: { _errors: ["City is required"] },        // nested field errors  },}

returnValidationErrors

Throws a ActionServerValidationError that the framework catches and returns as result.validationErrors. It never returns — it always throws.

For expected non-validation errors ("out of stock", "not found"), the sibling helper returnServerError(payload) works the same way (throws internally, never returns) but sets result.serverError to the typed payload, bypassing handleServerError. See the safe-action-client skill.

ts
"use server";
import { z } from "zod";import { returnValidationErrors } from "next-safe-action";import { actionClient } from "@/lib/safe-action";
const registerSchema = z.object({  email: z.string().email(),  username: z.string().min(3),});
export const register = actionClient  .inputSchema(registerSchema)  .action(async ({ parsedInput }) => {    // Check business rules after schema validation passes    const existingUser = await db.user.findByEmail(parsedInput.email);    if (existingUser) {      returnValidationErrors(registerSchema, {        email: { _errors: ["This email is already registered"] },      });    }
    const existingUsername = await db.user.findByUsername(parsedInput.username);    if (existingUsername) {      returnValidationErrors(registerSchema, {        username: { _errors: ["This username is taken"] },      });    }
    // Both checks passed — create the user    const user = await db.user.create(parsedInput);    return { id: user.id };  });

Root-Level Errors

Use _errors at the top level for form-wide errors:

ts
returnValidationErrors(schema, {  _errors: ["You can only create 5 posts per day"],});

Supporting Docs

  • Custom validation errors and returnValidationErrors patterns
  • Formatted vs flattened shapes, per-action override

Displaying Validation Errors

tsx
// Formatted shape (default){result.validationErrors?.email?._errors?.map((error) => (  <p key={error} className="text-red-500">{error}</p>))}
// Root-level errors{result.validationErrors?._errors?.map((error) => (  <p key={error} className="text-red-500">{error}</p>))}
tsx
// Flattened shape{result.validationErrors?.fieldErrors?.email?.map((error) => (  <p key={error} className="text-red-500">{error}</p>))}
// Form-level errors (flattened){result.validationErrors?.formErrors?.map((error) => (  <p key={error} className="text-red-500">{error}</p>))}

来源与署名

来源:next-safe-action/skills位于skills/safe-action-validation-errors提交a2605bd

许可证: 无许可证

内容归原作者所有。SourceWeft 从公开仓库中收录这些内容。

举报或申请下架