11

How can I create a custom 404 page in Drupal 8?

I have created a new page(Content) in the backoffice called 404 (node number 100). I have set it as the 404 default page at Configuration > Basic site settings.

Settings

It works with the content that I have set in the Backoffice.

But now I want it to be editable programatically and I don't know how can I create the overriding file.

I have tried to create mytheme/templates/html--node--100.html.twig and it works only when the request its directly that url (node/100), but it doesn't work when you try a random slug on the URL and drupal has to resolve it. When this happens, drupal is serving me the content that the 404 page has in the backoffice and not in the file that I have just created.

I have tried several files like page--404-html.twig, html--node--404.html.twig, html--page--404.html.twig,... but it doesn't work neither

Can anyone lend me a hand?

DarkBee
  • 16,592
  • 6
  • 46
  • 58
cadev
  • 123
  • 1
  • 2
  • 9

4 Answers4

13

page--system--404.html.twig (or the equivalent for other 4xx statuses) no longer works in Drupal 8.3 as the 4xx response handling has changed. You'll now need the core patch from https://www.drupal.org/node/2363987 or a similar custom module hook that adds template suggestions for these pages:

/**
 * Implements hook_theme_suggestions_page() to set 40x template suggestions
 */
function MYMODULE_theme_suggestions_page(array $variables) {
  $path_args = explode('/', trim(\Drupal::service('path.current')->getPath(), '/'));
  $suggestions = theme_get_suggestions($path_args, 'page');
  $http_error_suggestions = [
    'system.401' => 'page__401',
    'system.403' => 'page__403',
    'system.404' => 'page__404',
  ];
  $route_name = \Drupal::routeMatch()->getRouteName();
  if (isset($http_error_suggestions[$route_name])) {
    $suggestions[] = $http_error_suggestions[$route_name];
  }

  return $suggestions;
}

EDIT: It's probably nicer to use hook_theme_suggestions_page_alter to modify the suggestions array. See an updated version of this code in https://www.drupal.org/project/fourxx_templates (or https://github.com/ahebrank/fourxx_templates/blob/8.x-1.x/fourxx_templates.module)

ahebrank
  • 254
  • 2
  • 4
  • This only works as long as you didn't set a custom 404 page in the configuration. At least in my case (Drupal `8.4.4`) `\Drupal::routeMatch()->getRouteName()` returns `"entity.node.canonical"`. Any pointers to how to identify and alter the 404 page in such a case? – fritzmg Mar 22 '18 at 09:13
  • It seems in that case you need to do this: https://drupal.stackexchange.com/a/231652/80492 – fritzmg Mar 22 '18 at 09:17
  • I think you should prefer using `HOOK_theme_suggestions_page_alter(array &$suggestions, array $variables)` otherwise you are overriding `$suggestions` array. It something you probably want to avoid when using, e.g., Context module which provides page templates too. – Raphael Larrinaga Apr 13 '18 at 10:23
  • @RaphaelLarrinaga, you're probably right. I've updated https://www.drupal.org/project/fourxx_templates to take that into account. – ahebrank Jun 19 '18 at 12:09
12

The following implementation adds a template suggestion for page, in this case if you create a page--404.html.twig file in your theme, you'll be able to customize the page and works with Drupal 8.5.1

MYTHEME.theme

/**
 * Implements hook_theme_suggestions_HOOK_alter().
 */
function MYTHEME_theme_suggestions_page_alter(&$suggestions, $variables, $hook) {
  /**
   * 404 template suggestion.
   */
  if (!is_null(Drupal::requestStack()->getCurrentRequest()->attributes->get('exception'))) {
    $status_code = Drupal::requestStack()->getCurrentRequest()->attributes->get('exception')->getStatusCode();
    switch ($status_code) {
      case 404: {
        $suggestions[] = 'page__' . (string) $status_code;
        break;
      }
      default:
        break;
    }
  }
}

and create a template called page--404.html.twig and override with your stuff.

OR,
if you want to add suggestions for all error pages, just take out the switch statement.

/**
 * Implements hook_theme_suggestions_HOOK_alter().
 */
function MYTHEME_theme_suggestions_page_alter(&$suggestions, $variables) {
  /**
   * error page template suggestions.
   */
  if (!is_null(Drupal::requestStack()->getCurrentRequest()->attributes->get('exception'))) {
    $status_code = Drupal::requestStack()->getCurrentRequest()->attributes->get('exception')->getStatusCode();
    $suggestions[] = 'page__' . (string) $status_code;
  }
}
2pha
  • 9,798
  • 2
  • 29
  • 43
Israel Morales
  • 1,681
  • 1
  • 14
  • 6
2

You can now use page--404.html.twig. Just be sure you don't set a node as the 404 page. Source: https://www.drupal.org/node/2960810

John
  • 1,324
  • 3
  • 14
  • 19
  • You can also use specific preprocess functions for each error code, like: ```function TEMPLATE_preprocess_page__4xx(&$vars) { }``` – Interdruper Nov 18 '20 at 17:03
0

Try page--system--404.html.twig

n8tron
  • 109
  • 9