I want to redirect users with RedirectResponse and display a message, but the message is not displayed.

$response = new RedirectResponse($url);

After little debugging I found that my initial (source) URL is loaded twice, and the messages (added with drupal_set_message()) are removed from the session in drupal_get_messages(). So I have no messages on my target $url.

How can I achieve this?

I'm doing it in hook_field_widget_form_alter().

  • 1
    Redirect in a form alter? what are you trying to do? That seems scary. Whenever possible, you should return a redirect response, so that it can be handled by Drupal as necessary. You can't do that in a form alter, but you can set a redirect url or response in a submit callback to $form_state. Consider using that. – Berdir Apr 22 '16 at 22:42
  • Problem is that I have form with complex custom elements. This form will work only with GET params. If user will open this form without GET params (for example with manual typing the url), he will be redirected on the dashboard. – Eugene Apr 23 '16 at 5:58

Set the repeat parameter in drupal_set_message() to TRUE and it will work:

$response = new RedirectResponse($url);
drupal_set_message(t('My message after redirect'), 'status', TRUE);
  • 1
    will work but only the second time you made the redirect. – Adrian Cid Almaguer Nov 16 '17 at 21:24
  • okay then... only spent 6 hours trying to debug this hell, and this answer did it... THANK YOU! – Raf A. Dec 18 '17 at 19:52
  • Block 'Status' under admin>blocks should be enabled to make the message visible.Else you wont see the message. – Jignesh Rawal Nov 22 '18 at 12:30
  • 1
    drupal_set_message is being deprecated, use the Messenger service instead. – rreiss Nov 25 '18 at 13:58

I had this same issue, but using an exit to end the script is not a good idea. Drupal has shutdown functions that it runs at the end of a page load which can be important. Instead I just had to return the redirect response directly:

public function buildForm(array $form, FormStateInterface $form_state) {
  $wizard_data = $form_state->getTemporaryValue('wizard');

  if (empty($wizard_data['csv_data'])) {
    drupal_set_message($this->t('Please upload a file first.'), 'error');
    return $this->redirect('my.route')->send();
  • Where is located this function buildForm? – Eugene Dec 8 '16 at 17:37
  • @Eugene buildForm is part of the Form controller class that extends \Drupal\Core\Form\FormBase. For example valuebound.com/resources/blog/… the buildForm function is inside the ResumeForm class. – masterchief Dec 8 '16 at 21:41
  • Does it means that your approach will not work for hook_form_alter()? How can I use your approach for node edit form? – Eugene Dec 9 '16 at 5:34
  • @Eugene it may work in hook_form_alter(), but you will not have access to the $this->redirect function (that comes from UrlGeneratorTrait). That means you'll need to create a \Drupal\Core\Url object and pass that into a \Symfony\Component\HttpFoundation\RedirectResponse object and return that. It'll have the same affect though. – masterchief Dec 11 '16 at 21:56
  • Yes, it will work, but the message will be not displayed as I explained in the initial message of this thread. Unfortunately it's not solution for my case :( – Eugene Dec 12 '16 at 4:21


// Drupal\Core\Url; // Symfony\Component\HttpFoundation\RedirectResponse; $url = Url::fromUri('internal:/'); $response = new RedirectResponse($url->toString()); $response->send();

Messeges using static service:


Other equivalents:

addMessage(), addError(), addWarning().







I would say that the solution, is not to send the response yourself but in your return.

return $response;
  • it's kind of obvious, but it solved my problem – Asy Oct 6 '16 at 7:39

After some investigation I have found that I should interrupt script right after the response. You should be very careful with this approach, because it can break some important actions.

$response = new RedirectResponse($url->toString());
  • 1
    I wouldnt kill the script. I would just look for the URL being called twice, and use another hook like hook_init or something to replace the messages that should be retained after the redirect. Alternatively dont redirect (302) but like use something like drupal_goto which is an internal drupal "go here" without the page refresh. – tenken Apr 22 '16 at 19:54

Works for me inside Controller callback. Should not use send(), but just return RedirectResponce object.

drupal_set_message(t('Please log in or create new account.'));
$url = Url::fromRoute('user.login');
$response = new RedirectResponse($url->toString());
return $response;

Recreate the logout functionality. It's just calling user_logout() function.

For this, I create:

A method in SomeController

public function logout() {
  return $this->redirect('<front>', [], ['query' => ['logout' => 1]]);

An event subcriber, subscribe to KernelEvents::REQUEST

$queryLogout = \Drupal::request()->query->get('logout');
if (!empty($queryLogout) && $queryLogout == 1) {
  drupal_set_message("You are logged out");

A router subcriber, altering user.logout route's controller

protected function alterRoutes(RouteCollection $collection) {

  // Change controller who handle logout.
  if ($routeLogout = $collection->get('user.logout')) {
    $routeLogout->setDefault('_controller', '\Drupal\my_module\Controller\SomeController::logout');

Don't use send() function, just return $response and it works.

$response = new RedirectResponse(\Drupal::url('user.login'));
// $response->send();
return $response;
  • This answer does not provide any more information than any of the previously given answers... - Consider upvoting the answer of Asy instead. – Mario Steinitz Sep 5 '18 at 13:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.