How Drupal displays validation errors to usersfor Drupal 8 , 9 , 10 , and 11

Last updated :  

You've now seen three different ways to report a validation failure — setError() on an element, setErrorByName() on a named field, and the automatic messages from #required/#upload_validators. This lesson is about what happens next: how those reported errors actually reach the person filling out the form, and how much control you have over that presentation.

What you'll learn in this lesson

  • How Drupal renders validation errors next to their field automatically
  • Why form_set_error(), which you may see in older tutorials, no longer exists
  • How to check whether the form has any errors at all from within your own code
  • The relationship between field-level error styling and the messages region at the top of the page
A function you'll see in old tutorials that no longer exists: Drupal 7 used a procedural function called form_set_error($name, $message) to report validation errors. It was removed entirely in Drupal 8's move to object-oriented Form API. If you find code using it, the direct modern replacements are $form_state->setErrorByName($name, $message) (by field name) or $form_state->setError($element, $message) (by element array) — both covered in earlier lessons.

How Drupal displays a reported error

Once setError()/setErrorByName() has been called during validation, you don't write any display code yourself — Drupal's form renderer handles it automatically in two places at once:

  • The specific field is visually marked (typically a red border) and the message you passed appears directly beneath it.
  • The same message also appears in the page's general messages region at the top, so it's visible even if the flagged field has scrolled out of view.

This dual placement is deliberate: the inline message tells you exactly which field is wrong, while the top-of-page message guarantees the visitor sees *that* something went wrong even on a long form where the broken field isn't currently visible.

Checking whether the form has errors, programmatically

if ($form_state->hasAnyErrors()) {
  // At least one validator reported a problem.
}

hasAnyErrors() is useful when a later piece of your own validation logic needs to behave differently depending on whether an earlier check already failed — for example, skipping an expensive cross-field comparison if a required field is already known to be empty, since the comparison would be meaningless anyway.

See it for yourself

Trigger a validation error on a field partway down a long form. Confirm you see the error message twice: once inline next to the field itself, and once in the general messages area at the top of the page.

Quick check: you're maintaining an older custom module and find a line calling form_set_error('email', 'Invalid email address.'). Will this still work on a Drupal 10/11 site? (Answer: no — form_set_error() was removed entirely when Drupal 8 moved the Form API to an object-oriented model. The call would trigger a fatal "call to undefined function" error; it needs to be rewritten as $form_state->setErrorByName('email', $this->t('Invalid email address.')).)

Key takeaways

  • Drupal automatically displays any reported validation error both inline next to its field and in the top-of-page messages region — no display code required from you.
  • form_set_error() is Drupal 7-only and was removed entirely in Drupal 8+; use $form_state->setErrorByName() or $form_state->setError() instead.
  • $form_state->hasAnyErrors() lets your own validation logic check whether an earlier check has already failed.
  • The dual inline-plus-top-of-page display exists specifically so errors are visible even on long forms where the broken field has scrolled out of view.

Coming up next

You've now covered the entire validation phase end to end. Next, the tutorial moves into a related but distinct concern: how a module can reach into and modify *someone else's* form entirely, using hook_form_alter() — including altering that form's validation behavior from outside.