How to display messages "properly" when using ajax submit? Here is a simple form:
  public function buildForm(array $form, FormStateInterface $form_state)
  {
    $form['some_text'] = [
      '#type'  =&gt; 'textfield',
      '#title' =&gt; $this-&gt;t('TextValue'),
    ];
    $form['submit'] = [
      '#type'  =&gt; 'submit',
      '#value' =&gt; $this-&gt;t('Submit'),
    ];
    return $form;
  }

  public function validateForm(array &amp;$form, FormStateInterface $form_state)
  {
    if ($form_state-&gt;getValue('some_text') != 'Awesome') {
      $form_state-&gt;setErrorByName('some_text', $this-&gt;t('Please enter &quot;Awesome&quot;'));
    }
  }

  public function submitForm(array &amp;$form, FormStateInterface $form_state)
  {
    drupal_set_message($this-&gt;t('The form was submitted'));
    $form_state-&gt;setRedirectUrl(Url::fromRoute('&lt;front&gt;'));
  }

And it works as expected:
Case 1A: Submit with no entry gives this (error message in default message location):

Case 1B: Submit with &quot;Awesome&quot; in TextValue gives this (completion message  in default message location and back to the front page of the site):

Now, I add some ajax on the submit button:
$form['submit'] = [
  '#type'  =&gt; 'submit',
  '#value' =&gt; $this-&gt;t('Submit'),
  '#ajax'  =&gt; [
    'wrapper'  =&gt; 'default_form_wrapper',
    'callback' =&gt; '::ajaxCallback',
    'progress' =&gt; [
      'type'    =&gt; 'throbber',
      'message' =&gt; $this-&gt;t('Be patient'),
    ],
  ],
];
$form['#prefix'] = '&lt;div id=&quot;default_form_wrapper&quot;&gt;';
$form['#suffix'] = '&lt;/div&gt;';

and the corresponding callback:
  public function ajaxCallback(array &amp;$form, FormStateInterface $form_state)
  {
    if ($form_state-&gt;hasAnyErrors()) {
      return $form;
    }
  }

And it works more or less as expected:
Case 2A: Submit with no entry gives this (almost OK, wrong location of the message):

Case 2B: Submit with &quot;Awesome&quot; in TextValue gives nothing (KO, no message and form is still displayed instead of front page).
And if I refresh the page in the browser, I get this:

As you can see, the location of the message area in case 2A is above form in default_form_wrapper
(to be compared to the default message area location, a div with class=&quot;region region-highlighted&quot;):


How can I make it work as I expect?

Have the message in the &quot;default&quot; area?
Have my submitForm work after all?
Finally, after hours digging Drupal Answers, I made it work this way.
My ajaxCallback:
$response = new AjaxResponse();
if ($form_state-&gt;hasAnyErrors()) {
  $messages = \Drupal::messenger()-&gt;deleteAll();
  $messages = [
    '#theme'        =&gt; 'status_messages',
    '#message_list' =&gt; $messages,
  ];
  $response-&gt;addCommand(new ReplaceCommand('#messages', ''));
  $response-&gt;addCommand(new AppendCommand('.region-highlighted', $messages));
}
else {
  $response-&gt;addCommand(new \Drupal\Core\Ajax\RedirectCommand(Url::fromRoute('&lt;front&gt;')-&gt;toString()));
  }
}
return $response;

and my submitForm is now empty!
Nota: $response-&gt;addCommand(new ReplaceCommand('#messages', '')); is here to have a new error message replacing a previous one (without this command, all the messages are displayed one after the other...).