setError
Manually set validation errors on fields.
</> setError: UseFormSetError
This function allows you to manually set an error on a field. You can call it multiple times to set errors on multiple fields.
Props
| Name | Type | Description |
|---|---|---|
name | string | input's name. |
error | { type?: string, message?: string, types?: MultipleFieldErrors } | type (optional) — An identifier for the error source (e.g. "required", "custom", "serverError"). Exposed as errors[name].type.message (optional) — The human-readable error message. Exposed as errors[name].message.types (optional) — A Record<string, string | boolean> that assigns multiple messages to a single field, keyed by error type (e.g. { required: "This is required", minLength: "Too short" }). Exposed as errors[name].types. Use this instead of message when you need to display more than one validation message for the same field simultaneously — set criteriaMode: "all" on the form if you also want built-in/schema validation to populate types the same way. |
| options | { shouldFocus?: boolean } | Should focus the input during setting an error. This only works when the input's reference is registered, it will not work for custom register as well. |
RULES
- This method will not persist the associated input error if the input passes
register's associated rules.register("registerInput", { minLength: 4 })setError("registerInput", { type: "custom", message: "custom message" })// validation will pass as long as minLength requirement pass - An error that is not associated with an input field will be persisted until cleared with
clearErrors. This behavior is only applicable for built-in validation at the field level.setError("notRegisteredInput", { type: "custom", message: "custom message" })// clearErrors() needs to be invoked manually to remove that custom error - Since v7.43.0 You can set a server or global error with
rootas the key. This type of error will not persist with each submission.
setError("root.serverError", {type: "400",})
shouldFocusdoesn't work when an input has been disabled.- This method will force
formState.isValidtofalse. However,isValidis always derived from the validation results of your registered inputs or schema. - Avoid using
type,root,ref,types,message, orformas field names — these collide with the internal shape ofFieldError/GlobalError.
Examples:
Single Error
import { useEffect } from "react"import { useForm } from "react-hook-form"type FormInputs = {username: string}const App = () => {const {register,handleSubmit,setError,formState: { errors },} = useForm<FormInputs>()const onSubmit = (data: FormInputs) => {console.log(data)}useEffect(() => {setError("username", {type: "manual",message: "Dont Forget Your Username Should Be Cool!",})}, [setError])return (<form onSubmit={handleSubmit(onSubmit)}><input {...register("username")} />{errors.username && <p>{errors.username.message}</p>}<input type="submit" /></form>)}
Multiple Errors
setError sets exactly one error per call. To set errors on multiple fields, call it once per field — typically in a loop over the server's error response.
import { useForm } from "react-hook-form"type FormInputs = {username: stringfirstName: string}const App = () => {const {register,handleSubmit,setError,formState: { errors },} = useForm<FormInputs>()const onSubmit = (data: FormInputs) => {console.log(data)}return (<form onSubmit={handleSubmit(onSubmit)}><label>Username</label><input {...register("username")} />{errors.username && <p>{errors.username.message}</p>}<label>First Name</label><input {...register("firstName")} />{errors.firstName && <p>{errors.firstName.message}</p>}<buttontype="button"onClick={() => {const inputs = [{type: "manual",name: "username",message: "Double Check This",},{type: "manual",name: "firstName",message: "Triple Check This",},]inputs.forEach(({ name, type, message }) => {setError(name, { type, message })})}}>Trigger Name Errors</button><input type="submit" /></form>)}
Single Field Errors
Use types (with criteriaMode: "all") to attach multiple validation messages to a single field at the same time. Each key in the object is an error-type identifier; each value is the message to display for that rule.
import { useEffect } from "react"import { useForm } from "react-hook-form"type FormInputs = {lastName: string}const App = () => {const {register,handleSubmit,setError,formState: { errors },} = useForm<FormInputs>({criteriaMode: "all",})const onSubmit = (data: FormInputs) => console.log(data)useEffect(() => {setError("lastName", {types: {required: "This is required",minLength: "This is minLength",},})}, [setError])return (<form onSubmit={handleSubmit(onSubmit)}><label>Last Name</label><input {...register("lastName")} />{errors.lastName && errors.lastName.types && (<p>{errors.lastName.types.required}</p>)}{errors.lastName && errors.lastName.types && (<p>{errors.lastName.types.minLength}</p>)}<input type="submit" /></form>)}
Server Error
import { useForm } from "react-hook-form";const App = () => {const { register, handleSubmit, setError, formState: { errors } } = useForm({criteriaMode: 'all',});const onSubmit = async () => {const response = await fetch(...)if (response.statusCode > 200) {setError('root.serverError', {type: response.statusCode,})}}return (<form onSubmit={handleSubmit(onSubmit)}><label>Last Name</label><input {...register("lastName")} />{errors.root.serverError.type === 400 && <p>server response message</p>}<button>submit</button></form>);};
Video
The following video explains the setError API in detail.