UnprocessableEntity class represents an HTTP error response with status code 422. It is used to standardize "Unprocessable Entity" error responses, typically for form validation errors where the request syntax is correct but the semantic content is invalid.ts
import { UnprocessableEntity } from "@arkyn/server/unprocessableEntity";
UnprocessableEntity takes an object with structured validation data:data (optional): Any additional data related to the error, such as metadata or instructions for the client.fieldErrors (optional): An object mapping field names to error messages, indicating specific validation issues with individual fields.fields (optional): An object containing the original field values that caused the validation errors, allowing clients to repopulate form fields.message (optional): A descriptive message explaining the validation error. Defaults to "Unprocessable entity" if not provided.toResponse() - Converts the instance into a Response object with JSON body and Content-Type: application/json header.toJson() - Alternative method using Response.json() for generating the JSON error response.typescript
import { UnprocessableEntity } from "@arkyn/server/unprocessableEntity";// Basic form validation errorthrow new UnprocessableEntity({message: "Validation failed",fieldErrors: {email: "Invalid email format",password: "Password must be at least 8 characters",},fields: {email: "invalid-email",password: "123",},});// With additional data (e.g., scrollTo for auto-scroll to first error)throw new UnprocessableEntity({message: "Please fix the form errors",fieldErrors: { name: "Name is required" },fields: { name: "" },data: { scrollTo: "name" },});// Convert to Response objectconst error = new UnprocessableEntity({fieldErrors: { username: "Username already taken" },});return error.toResponse();
json
{"name": "UnprocessableEntity","message": "Validation failed","cause": {"data": { "scrollTo": "name" },"fieldErrors": {"email": "Invalid email format","password": "Password must be at least 8 characters"},"fields": {"email": "invalid-email","password": "123"}}}
422, set on the Response object itself, the status code is not part of the JSON body. Note that data, fieldErrors, and fields are nested inside cause, not top-level keys. This cause is assigned directly as the object { data, fieldErrors, fields }, so it stays a nested object in the response body. As of v3.0.12, every other BadResponse subclass works the same way, cause is no longer JSON-stringified anywhere, see Breaking Changes.SchemaValidator.formValidate() and SchemaValidator.formAsyncValidate():typescript
import { SchemaValidator } from "@arkyn/server/schemaValidator";import { z } from "zod";const schema = z.object({email: z.string().email("Invalid email"),name: z.string().min(1, "Name is required"),});const validator = new SchemaValidator(schema);// formValidate throws UnprocessableEntity on validation failureconst data = validator.formValidate(formData, "Please fix the errors");
fields property preserves the original input values, allowing forms to repopulate fields after a validation error.fields and data are redacted with parseSensitiveData before being stored on cause, so a value submitted under a sensitive key (password, token, authorization, secret, etc., matched case-insensitively, including nested objects) is masked in the response body instead of being echoed back in clear text. fieldErrors is untouched, it only ever contains messages, not the submitted values. Unlike every other BadResponse subclass, UnprocessableEntity's cause is still included in production responses (NODE_ENV === "production"), it's redacted, structured data meant for the client to repopulate a form, not internal diagnostic detail. See Breaking Changes for the production cause behavior of the other BadResponse classes, and the v3.0.12 entry for the JSON-stringification change that now makes all subclasses consistent.data property is passed through as-is, @arkyn/server does not read or act on it in any special way. A key like scrollTo naming the first error field is just a convention some consumers use; interpreting it (e.g. to scroll to the field) is entirely up to your own frontend code, not something the library implements.UnprocessableEntity (422) for semantic validation errors. Use BadRequest (400) for malformed syntax or missing required parameters.