This project is not covered by Drupal’s security advisory policy.
A themable, brandable replacement for Drupal's plain-text
"The website encountered an unexpected error. Please try again later."
message, backed by a static HTML fallback for the moments when Drupal
itself is on fire.
Why this module
Drupal's built-in error page is unbranded, uninformative, and in the
worst case (fatal PHP or database failure) not served at all. This
module replaces it with a fully themed, configurable page AND a
pre-rendered static snapshot the web server can serve when Drupal
cannot run.
Features
-
Themed application-level error page. Intercepts the
kernel exception flow and renders a branded page through Twig for
uncaught exceptions and HTTP 500 / 503 responses. -
Two-tier resilience.
Tier 1 renders live when Drupal is alive but the request
failed. Tier 2 is a static HTML snapshot written to
public://branded_error_page/with inline CSS and zero
external assets, mapped viaErrorDocument(Apache) or
error_page(Nginx). -
Per-error-type branding. Separate title, message
body, technical-details toggle, optional logo / support-email /
support-URL overrides, a "Back to homepage" toggle, and up to three
extra call-to-action buttons for HTTP 500, 503, and a generic
catch-all. -
Reference IDs. Every error gets a short
eight-character token, logged to thebranded_error_page
channel and surfaced on the page so support staff can correlate
user reports with the underlying log entry. -
Safe technical-details reveal. Stack traces are
gated by three independent checks: per-type config toggle,
access site reportspermission, and
system.logging:error_levelofverboseor
all. Anonymous users never see them, regardless of
config. -
Optional 403 / 404 handling. Off by default. When
enabled, still defers to any custom
system.site:page.403/page.404you have
configured, so existing custom pages always win. -
Drush integration.
drush branded-error-page:regenerate
(aliasbep:regen) rebuilds snapshots on demand. -
Live preview. Each error type renders in a new tab
from the settings form, using sample content with a synthetic
reference ID. -
Accessible. Semantic HTML, proper heading
hierarchy, ARIA live region for the reference token, no
color-only signaling. -
Themeable. CSS custom properties, a single Twig
template, and a preprocess hook for downstream overrides.
How the two tiers work
Tier 1: a KernelEvents::EXCEPTION
subscriber runs at a low priority, after core's logging and
format-negotiation subscribers, and produces a themed response for
requests that accept HTML. JSON / API clients are left to core.
Tier 2: on config save, install, and on demand via
Drush, the module renders each error type to a standalone HTML file
under public://branded_error_page/. The file is fully
self-contained (inline CSS, logo inlined as an absolute URL) so it
works when PHP, the database, or the theme system is unavailable.
Map it via your web server:
# Nginx error_page 500 502 504 = @branded_500; error_page 503 = @branded_503; location @branded_500 { internal; root /var/www/html/web; try_files /sites/default/files/branded_error_page/500.html =500; } location @branded_503 { internal; root /var/www/html/web; try_files /sites/default/files/branded_error_page/503.html =503; }
# Apache ErrorDocument 500 /sites/default/files/branded_error_page/500.html ErrorDocument 502 /sites/default/files/branded_error_page/500.html ErrorDocument 503 /sites/default/files/branded_error_page/503.html ErrorDocument 504 /sites/default/files/branded_error_page/500.html
Configuration
Visit Configuration > System > Branded Error Page
(/admin/config/system/branded-error-page). The form is
grouped into global branding, three per-type fieldsets (HTTP 500, 503,
Generic), and a snapshot section. Each error type supports:
- Title, filtered message body, technical-details toggle.
-
Per-type logo, support email, and support URL overrides. All three
inherit from the global branding when left blank. - A "Back to homepage" link toggle, rendered as a tertiary action.
-
Up to three extra call-to-action buttons, each with a label and a
URL. Validation rejects non-http(s)URLs and paths
that do not start with/.
Permissions
The settings form is gated by
administer branded error pages, which deliberately
does NOT require administer site configuration so brand
control can be delegated to a content-ops role without granting full
site-config access. Viewing technical details on the rendered page
additionally requires access site reports.
How it differs from similar modules
| Module | What it does | How this differs |
|---|---|---|
| Custom Error | Lets you set the body of 403 / 404 pages via routes you define. |
Route-based, so it can only help when Drupal is able to render. Branded Error Page intercepts the exception flow itself and adds the Tier 2 static fallback for when Drupal cannot run. |
| Fast 404 | Short-circuits 404s for asset paths to skip a full bootstrap. |
Performance optimization for known-missing assets. Branded Error Page is a branding and resilience layer for fatal failures. The two compose well; install both. |
Requirements
- Drupal 10.3 or later, or Drupal 11.
- PHP 8.1 or later.
- A writable
public://filesystem for Tier 2 snapshots. - Drush 12+ (optional, for the regenerate command).
No contrib dependencies.
Security
- Message bodies always pass through a filter format. Default install uses
restricted_html. - Technical-details reveal is gated by three independent checks; anonymous users
never see stack traces. - Logo uploads are restricted to image mimetypes.
- Reference IDs are random, not sequential, and reveal no internal state.
- The static snapshot contains no secrets, only configured public branding text,
the logo, and CSS.
Roadmap
Will do:
- Per-language snapshot files with server-side
Accept-Language
mapping. - Webhook on snapshot regeneration so external CDN purges can hook in.
- Lando / DDEV recipes under
/recipesonce the API stabilizes.
Will not do:
- Full WYSIWYG page builder for the error page. Use a theme.
- Automatic incident reporting to third parties. Wire your own handler to the
branded_error_pagelog channel.
Documentation and support
- Full configuration walkthrough, Twig variable reference, and troubleshooting
guide are in the module'sREADME.md. - Issues and feature requests: use the issue queue on this project page.
- Security issues: please follow the standard Drupal security reporting
process.
Project information
No further development
No longer developed by its maintainers.- Project categories: Accessibility, Content display
1 site reports using this module
- Created by talishkhan on , updated
This project is not covered by the security advisory policy.
Use at your own risk! It may have publicly disclosed vulnerabilities.
