I have created a custom 404 page using hook_preprocess_page():

function THEME_preprocess_page(&$variables) {
  $header = drupal_get_http_header('status');
  if($header == '404 Not Found') {
    $variables['theme_hook_suggestions'][] = 'page__404';

The contents of page--404.tpl.php is identical to the contents of page.tpl.php except that use a static text block instead of calling print render($page['content']);. When this page is displayed one of the menus disappears from the header. Everything else look just as it does when I'm on a ordinary page except for the menu.

Since I only wan't to change the actual message that is displayed when receiving a 404 page and still use the rest of the markup contained in page.tpl.php perhaps it would be a better idea to only alter the $page['content'] inside a hook or similar?

Would appreciate if anyone could help me figure out why the menu is vanishing or could give me a solution that only alters the $page['content'] in page.tpl.php in case of a 404.

  • Did you manage to find a solution? Sep 15, 2015 at 1:03
  • @AlvinPascoe - Yes, I did. In the end I used the function hook_404() to override the error message which in turn solved the problem. Not really sure why this happend from the beginning though. Sep 15, 2015 at 3:42

2 Answers 2


If you can accept using a module for this, rather than a theme override, you should be able to use CustomError:

This module allows the site admin to create custom error pages for HTTP status codes 403 (access denied) and 404 (not found), without the need to create nodes for each of them.

Just to make sure I've understood the use case: You write:

Since I only wan't to change the actual message that is displayed when receiving a 404 page

This message is by default "Page not found The requested page "..." could not be found. ". I think CustomError' will reproduce the standard message unless you override this - but it may something about your use case that I have not understood.

  • I was considering this module, but I think it would be nicer to simply use some kind of preprocess hook. Seems like a litte too much to use a module for such a small task. May 23, 2015 at 6:14
  • 1
    OK. I am curious about the resistance I've seen from developers (not only you) for using modules to solve problems. With proper caching (IMHO a must if you use Drupal in all sort of configurations), I've found that the performance (page bootstrap speed) is just as fast as adding a preprocess hook myself, and the memory footprint just a little bit larger. May 23, 2015 at 7:09
  • That might very well be the truth but I'm also curious about how to simply modify the content of the page. I know I can use a module, but I would also like to learn how to do this by myself. May 23, 2015 at 7:11
  • 1
    "I would also like to learn how to do this by myself". I respect that. Perhaps you should add this motivation to the question to make it clear to people trying to help you what it is your question really is about? I clearly did interprete your statement "or could give me a solution" too broad. May 23, 2015 at 7:31
  • +1 for @FreeRadical 's answer, and the related comments ... Why make it easy (using a module), if you can make it complicated also, right? I can understand one wants to use the opportunity to "learn" from such cases, but what about things like future maintenance (upgrades, etc) of custom modules? Other reasons for not using a contrib module I sometimes experience are (a) not knowing "there is a module for it", or (b) jobsecurity / jobprotection reasons ... Aug 20, 2015 at 13:33

One option would be to update your THEME_preprocess_page function to initialise a custom boolean variable based on whether the page returns a 404.

function THEME_preprocess_page(&$variables) {
  $header = drupal_get_http_header('status');
  $variables['page']['page_not_found'] = false;
  if($header == '404 Not Found') {
    $variables['page']['page_not_found'] = true;

You could then use this custom variable in your page.tpl.php (similar to how you check for $logo or $site_title) to display either the custom 404 text or $page['content'].

<?php if($page['page_not_found']): ?>
    <p>CUSTOM 404 TEXT</p>
<?php else: ?>
    <?php print render($page['content']); ?>
<?php endif; ?>

I would only recommend doing this if the 404 page contains only minor changes to a standard page. Otherwise, a different template file woild be the way to go.

Regarding the menu issue, I believe by default the primary links are hidden on 404 pages. This topic is discussed on drupal.org here, 'setvik' states the following solution:

To work-around the problem, do the following:

1) Create a custom node to handle "Page not found"'s.

2) go to Admin -> Site Configuration -> Error Reporting and set the "Default 404 (not found) page:" to the node you just created.

I can vouch for this as I've had to do it myself numerous times in the past.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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