Drupal Errors: Display Errors, Read Logs, and Find the Real Failure
If your Drupal site says "The website encountered an unexpected error. Try again later.", do not start by editing random Twig files. Start by collecting the exact failure: the error-display setting, the Recent log messages row, the Status report, and the route or screen that triggered it. We reproduced the workflow in Drupal 11.3.8 on Docker and captured the screens below.
What we actually tested
- Installed Drupal 11.3.8 from the official
drupal:11-apacheDocker image with PostgreSQL 16 and Drush 13.7.2. - Enabled Drupal core Database Logging (
dblog). - Created a tiny local custom module route at
/simplereview-error-labthat throws a controlledRuntimeException. - Captured the generic public error page, Logging and errors settings, Recent log messages, and Status report.
The safe debugging order
Use this order when Drupal shows a generic error page or a blank screen. It keeps production safe and turns "Drupal is broken" into a concrete fix brief.
- Do not enable verbose errors publicly first. If the site is live, reproduce on local or staging. Verbose output can expose paths, class names, query details, and module structure.
- Check Status report. It tells you whether the install is already unhealthy: cron, trusted host, filesystem, PHP extensions, update status, or database warnings.
- Open Recent log messages. If
dblogis enabled, use/admin/reports/dblog. Filter by severity and type. If the site is too broken for the UI, use Drush watchdog commands. - Only then change error display. Drupal documents
hide,some,all, andverbose. Switch temporarily, collect the trace, then switch back. - Map the trace to the boundary. Theme/Twig, config, custom module, contributed module, environment, or database migration all have different risk.
How to display Drupal errors without leaking production details
Drupal's official verbose logging page says the browser UI is under /admin/config/development/logging. The same setting can be changed with Drush:
vendor/bin/drush config:set system.logging error_level verbose -y
vendor/bin/drush cr
For local development, Drupal's docs also mention PHP-level display settings such as error_reporting(E_ALL) and ini_set('display_errors', TRUE). Keep that distinction clear:
| Setting | Use it for | Do not use it for |
|---|---|---|
hide | Production default | Debugging a hidden exception without logs |
some / all | Staging reproduction where users cannot see output | Public traffic |
verbose | Short local/staging trace capture | Long-lived live-site setting |
PHP display_errors | Local PHP runtime diagnosis | Shared production hosting |
Read Recent log messages before changing code
The Drupal Database Logging docs say dblog records events in the database and exposes them at /admin/reports/dblog. That page is the bridge between the generic public error and the actual failing component.
In our lab, the public page only showed the generic sentence. The log showed a PHP RuntimeException and a custom simplereview_error_lab entry. That is enough to avoid editing unrelated templates or clearing cache repeatedly.
When SimpleReview can prepare the fix
SimpleReview is a fit when the evidence points to a bounded change:
- a Twig template or theme preprocess function throws the error;
- a custom module controller/service has a clear exception;
- a configuration value is wrong and the expected state is obvious;
- the Status report is healthy enough that this is not an environment incident.
The workflow is: capture the screen, capture the log row, let SimpleReview prepare a site-ready fix, verify on staging, then return production error display to hidden.
When to hire a Drupal developer instead
Bring in a Drupal developer when the log points to migration, schema, database state, security, or infrastructure ownership. Examples:
hook_update_N()half-ran and the database is in an unknown state;- a contributed module update broke entity schema or field storage;
- the error only happens under real traffic or cache layers;
- the log contains authentication, access, payment, or private-data failures;
- you cannot reproduce the issue outside production.
Copy-paste checklist
# 1. On staging/local, enable verbose Drupal error output temporarily.
vendor/bin/drush config:set system.logging error_level verbose -y
vendor/bin/drush cr
# 2. Reproduce the failing URL once.
curl -I https://example.com/the-broken-path
# 3. Read recent watchdog messages.
vendor/bin/drush watchdog:show --count=20
# 4. Put production-style display back.
vendor/bin/drush config:set system.logging error_level hide -y
vendor/bin/drush cr
Turn the Drupal error into a fix brief
Capture the failing screen and log row, then let SimpleReview prepare a bounded site-ready fix for review.
Install SimpleReview