Validation Utilities
next-safe-action exports several utility functions and constants for working with validation errors.
All utilities are imported from the main entry point:
import {
returnValidationErrors,
flattenValidationErrors,
formatValidationErrors,
DEFAULT_SERVER_ERROR_MESSAGE,
} from "next-safe-action";returnValidationErrors()
Throw validation errors from server action code. This function never returns. It throws internally and the error is caught by the action builder and returned as validationErrors in the result.
function returnValidationErrors<S extends StandardSchemaV1>(
schema: S,
validationErrors: ValidationErrors<S>
): never;Parameters:
Prop
Type
Returns: never, this function always throws.
export const signUp = actionClient
.inputSchema(z.object({
email: z.string().email(),
username: z.string().min(3),
}))
.action(async ({ parsedInput }) => {
const emailExists = await db.user.findByEmail(parsedInput.email);
if (emailExists) {
// Throws internally, code below this line never executes
return returnValidationErrors(signUpSchema, {
email: { _errors: ["Email already registered"] },
});
}
// Form-level errors (not tied to a specific field)
return returnValidationErrors(signUpSchema, {
_errors: ["Registration is currently disabled"],
});
});returnValidationErrors accepts both direct schemas and async schema factory functions. When using an async factory (for i18n), pass the factory function itself.
flattenValidationErrors()
Transform formatted validation errors into a flat structure with formErrors and fieldErrors. Discards errors for nested fields (only keeps one level deep).
function flattenValidationErrors<VE extends ValidationErrors<any>>(
validationErrors: VE
): FlattenedValidationErrors<VE>;Parameters:
Prop
Type
Returns: FlattenedValidationErrors<VE>, an object with formErrors: string[] and fieldErrors: { [key]: string[] }.
// Input (formatted shape):
{
_errors: ["Passwords don't match"],
name: { _errors: ["Too short"] },
address: { street: { _errors: ["Required"] } },
}
// Output (flattened shape):
{
formErrors: ["Passwords don't match"],
fieldErrors: {
name: ["Too short"],
// address.street is discarded (nested)
},
}Usage with handleValidationErrorsShape
import { flattenValidationErrors } from "next-safe-action";
export const myAction = actionClient
.inputSchema(schema, {
handleValidationErrorsShape: (ve) => flattenValidationErrors(ve),
})
.action(async ({ parsedInput }) => { /* ... */ });formatValidationErrors()
Identity function that returns the formatted validation errors as-is. Useful as a named reference when you want to be explicit about using the default shape.
function formatValidationErrors<VE extends ValidationErrors<any>>(
validationErrors: VE
): VE;DEFAULT_SERVER_ERROR_MESSAGE
The default error message returned to the client when a server error occurs and no custom handleServerError is provided.
const DEFAULT_SERVER_ERROR_MESSAGE: string;
// Value: "Something went wrong while executing the operation."This constant is useful when you want to check if the client received the default error message, or when building custom error handlers that should fall back to the default.
import { DEFAULT_SERVER_ERROR_MESSAGE } from "next-safe-action";
const actionClient = createSafeActionClient({
handleServerError: (error) => {
if (error instanceof AuthError) {
return "Authentication failed";
}
return DEFAULT_SERVER_ERROR_MESSAGE;
},
});See also
- Custom Validation Errors — guide for customizing error shapes
- Error Handling — the complete error taxonomy
- Error Classes — all exported error classes