Drupal is a registered trademark of Dries Buytaert
drupal 11.3.7 Update released for Drupal core (11.3.7)! drupal 11.2.11 Update released for Drupal core (11.2.11)! drupal 10.6.7 Update released for Drupal core (10.6.7)! drupal 10.5.9 Update released for Drupal core (10.5.9)! cms 2.1.1 Update released for Drupal core (2.1.1)! drupal 11.3.6 Update released for Drupal core (11.3.6)! drupal 10.6.6 Update released for Drupal core (10.6.6)! cms 2.1.0 Update released for Drupal core (2.1.0)! bootstrap 8.x-3.40 Minor update available for theme bootstrap (8.x-3.40). menu_link_attributes 8.x-1.7 Minor update available for module menu_link_attributes (8.x-1.7). eca 3.1.1 Minor update available for module eca (3.1.1). layout_paragraphs 2.1.3 Minor update available for module layout_paragraphs (2.1.3). ai 1.3.3 Minor update available for module ai (1.3.3). ai 1.2.14 Minor update available for module ai (1.2.14). node_revision_delete 2.0.3 Minor update available for module node_revision_delete (2.0.3). moderated_content_bulk_publish 2.0.52 Minor update available for module moderated_content_bulk_publish (2.0.52). klaro 3.0.10 Minor update available for module klaro (3.0.10). klaro 3.0.9 Minor update available for module klaro (3.0.9). layout_paragraphs 2.1.2 Minor update available for module layout_paragraphs (2.1.2). geofield_map 11.1.8 Minor update available for module geofield_map (11.1.8).

error_page

2,249 sites Security covered
View on drupal.org

Shows a friendly page to the users when an exception or an error are thrown, instead of the plain page provided by Drupal core. The module is able to attach an Universally Unique Identifier (UUID) to each error/exception, so that the user is able to refer the error to the site's contact support team or help desk. The UUID is logged also in the Drupal log.

Compatibility

  • Branch 2.1.x is Drupal 10 and 11 compatible.
  • Branch 2.0.x is Drupal 9 compatible.
  • Branch 8.x-1.x is Drupal ^8.8 compatible.

Technical aspects

Drupal services, configuration, theming

Uncaught exceptions indicates that something really wrong has happened on a site. There is a great chance that some, or all, of Drupal services are not available. For this reason, in the module we are avoiding to use or refer Drupal services as much as possible. For the same reason, the module cannot be configured using the configuration management offered by Drupal. Instead, the module will use the settings stored in the settings.php file to configure its behavior.

This is true also for theming. The Drupal/Twig rendering engine cannot be used, as it would involve usage of Drupal services as well. However, the outputted page or message can still be customized because they are simple static HTML pages with some raw replacement tokens.

How it works?

Uncaught exceptions

The module swaps the core ExceptionLoggingSubscriber, which is responsible for logging the uncaught exceptions to the Drupal logger, with its own ErrorPageExceptionLoggingSubscriber. Actually the module class replaces the ::onError() method and logs also the UUID if it has been configured so. Then, the module adds a new subscriber, ErrorPageFinalExceptionSubscriber, which acts just before the core FinalExceptionSubscriber by showing the output in its own way and stopping the propagation of the KernelEvents::EXCEPTION event.

Fatal and user errors

The module uses its own error/exception handlers, instead of _drupal_error_handler() and _drupal_exception_handler(). Because those procedural functions are hard to be extended or overwritten, the core code is 95% copied in module's handlers. These are slightly changed to allow using a custom outputted HTML rendered markup.

Getting started

Install

Install the module as any other module. There are no other dependencies.

Configure

As explained earlier, the entire configuration is done via settings.php:

ErrorPageErrorHandler autoload

As the container might not be available yet when an uncaught exception or a fatal error occur, the auto-loading might not work for extensions such as modules. Thus we cannot register our error/exception handlers, which live in ErrorPageErrorHandler. The system must be instructed explicitly from where to load the class. If you are using composer this is done automatically because in the module's composer.json we've added the class as a classmap entry of autoload. If, for some reasons, you're not using Composer, then you'll need to explicitly require the file. In this case, in settings.php just add this line:

// Note that the path to error handler might be different on some installations.
require_once 'modules/custom/error_page/src/ErrorPageErrorHandler.php';

Set the custom error handlers

Next two lines should be added in `settings.php`:

set_error_handler(['Drupal\error_page\ErrorPageErrorHandler', 'handleError']);
set_exception_handler([
  'Drupal\error_page\ErrorPageErrorHandler',
  'handleException',
]);

Configuration

In settings.php:

// If to create a UUID for each exception/error. Defaults to TRUE.
$settings['error_page']['uuid'] = TRUE;
// Point to the path where the customizable HTML markup files are placed. It's
// recommended that the custom template location is placed outside the webtree
// or is protected from the public access with a file, such as markup/.htaccess.
// Defaults to the templates provided by module, in the `markup/` sub-directory.
$settings['error_page']['template_dir'] = DRUPAL_ROOT . '/../path/to/templates';

All together

Your settings.php section might look like:

// Only if you don't use composer.
require_once 'modules/custom/error_page/src/ErrorPageErrorHandler.php';
set_error_handler(['Drupal\error_page\ErrorPageErrorHandler', 'handleError']);
set_exception_handler([
  'Drupal\error_page\ErrorPageErrorHandler',
  'handleException',
]);
// Log the UUID in the Drupal logs.
$settings['error_page']['uuid'] = TRUE;
// Your templates are located in path/to/templates, one level above the webroot.
$settings['error_page']['template_dir'] = DRUPAL_ROOT . '/../path/to/templates';

Customizing the output page/message

By default the HTML markup page and message, displayed in case of error or exception, are very simple but they can be can be customized. Probably the word "themed" would be too much. In order to customize the output, the files markup/error_page.html and markup/error_message.html should be copied and edited in the location specified in $settings['error_page']['template_dir'].

Three variables can be used:

  • {{ uuid }}: The error/exception UUID, if any.
  • {{ base_path }}: The Drupal base path, as is returned by base_path(). This helps to build paths to images or other assets.
  • {{ error_report }}: The standard error and the error/exception backtrace. Note that the content of this variable is empty if the system error logging verbosity doesn't allow to show verbose error details such as the backtrace.

Don't forget to protect the templates location from public access or, even better, place them outside the web-tree.

Testing

The package contains a module, error_page_test, that simulates different kind of exceptions, errors or notices. As this is a testing module, before enabling, make sure Drupal allows discovery of testing module by ensuring this line in settings.local.php or settings.php:

$settings['extension_discovery_scan_tests'] = TRUE;

Warning: You should never enable extension_discovery_scan_tests setting in production. Discovering testing modules should be enabled only on development environments.

After installing error_page_test, you can test the following pages:

  • /error_page_test/exception: simulates an exception.
  • /error_page_test/fatal_error: simulates a fatal error.
  • /error_page_test/user_error: simulates a user error.
  • /error_page_test/php_notice: simulates a PHP notice.

By default, exceptions and fatal errors are logged also in the PHP log. For testing purposes, you can pipe the error log entries in a custom file:

// Check https://www.php.net/manual/en/function.error-log.php for details.
// A value of 3 sends the error log entries in a file. 
$settings['error_page']['log']['method'] = 3;
// Defines the destination file.
$settings['error_page']['log']['destination'] = 'temporary://erro_log.txt';

Activity

Total releases
2
First release
Mar 2025
Latest release
1 year ago
Release cadence
1 day
Stability
0% stable

Releases

Version Type Release date
2.1.0-beta1 Pre-release Mar 22, 2025
2.1.x-dev Dev Mar 21, 2025