# setError

> Manually set a validation error on one or multiple fields, with support for server-side and custom errors in React Hook Form.

Source: https://react-hook-form.com/docs/useform/seterror

## `setError:` [UseFormSetError](https://react-hook-form.com/ts#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`.<br/><br/>**`message`** _(optional)_ — The human-readable error message. Exposed as `errors[name].message`.<br/><br/>**`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.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |

> **Important: Rules**
>
> - This method will not persist the associated input error if the input passes `register`'s associated rules.
>   ```javascript
>   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.
>   ```javascript
>   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 `root` as
>   the key. This type of error will not persist with each submission.
>
> ```javascript
> setError("root.serverError", {
>   type: "400",
> })
> ```
>
> - `shouldFocus` doesn't work when an input has been disabled.
> - This method will force <code>formState.isValid</code> to <code>false</code>.
>   However, <code>isValid</code> is always derived from the validation results of your
>   registered inputs or schema.
> - Avoid using `type`, `root`, `ref`, `types`, `message`, or `form` as field names — these collide with the internal shape of `FieldError`/`GlobalError`.
>

### Examples

---

**Single Error**

**TS**

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-v7-ts-seterror-nfxxu)

```tsx
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>
  )
}
```

**JS**

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-v7-seterror-btbf8)

```javascript
import { useForm } from "react-hook-form"

const App = () => {
  const {
    register,
    setError,
    formState: { errors },
  } = useForm()

  return (
    <form>
      <input {...register("test")} />
      {errors.test && <p>{errors.test.message}</p>}

      <button
        type="button"
        onClick={() => {
          setError("test", { type: "focus" }, { shouldFocus: true })
        }}
      >
        Set Error Focus
      </button>
      <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.

**TS**

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-v7-ts-seterror-8h440)

```tsx
import { useForm } from "react-hook-form"

type FormInputs = {
  username: string
  firstName: 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>}
      <button
        type="button"
        onClick={() => {
          const inputs = [
            {
              type: "manual",
              name: "username",
              message: "Double Check This",
            },
            {
              type: "manual",
              name: "firstName",
              message: "Triple Check This",
            },
          ] as const

          inputs.forEach(({ name, type, message }) => {
            setError(name, { type, message })
          })
        }}
      >
        Trigger Name Errors
      </button>
      <input type="submit" />
    </form>
  )
}
```

**JS**

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-v7-seterror-3y1op)

```javascript
import { useForm } from "react-hook-form"

const App = () => {
  const {
    register,
    handleSubmit,
    setError,
    formState: { errors },
  } = useForm()

  const onSubmit = (data) => {
    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>}
      <button
        type="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.

**TS**

```tsx
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>
  )
}
```

**JS**

[Open in CodeSandbox](https://codesandbox.io/s/seterror-single-field-errors-79wcr9)

```javascript
import { useEffect } from "react"
import { useForm } from "react-hook-form"

const App = () => {
  const {
    register,
    handleSubmit,
    setError,
    formState: { errors },
  } = useForm({
    criteriaMode: "all",
  })
  const onSubmit = (data) => {
    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**

```javascript
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.status >= 400) {
        setError('root.serverError', {
          type: String(response.status),
        })
    }
  }

  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.

[Watch on YouTube](https://www.youtube.com/watch?v=raMqvE0YyIY)

### Tips

---

- Map field errors from your API onto the form, and focus the first one:

  ```javascript
  const onSubmit = async (data) => {
    const response = await save(data)
    if (!response.ok) {
      const { fieldErrors } = await response.json() // e.g. { email: "Already taken" }
      Object.entries(fieldErrors).forEach(([name, message], index) => {
        setError(
          name,
          { type: "server", message },
          { shouldFocus: index === 0 }
        )
      })
    }
  }
  ```

- Use `root.*` for errors that do not belong to one field, such as "Network error" or "Too many attempts". Root errors are cleared on the next submission. Show them with [`ErrorMessage`](https://react-hook-form.com/docs/useformstate/errormessage) and `name="root.server"`.
- Give server errors a `type` such as `"server"`. Then your UI can show them differently from client-side validation errors.
