When WordPress shows a white screen, “There has been a critical error on this website”, or a plugin misbehaves, the actual error message is hidden by default. Debug mode makes WordPress record PHP errors, warnings and notices, so you can see what’s wrong. On a production site, the key is to log errors without displaying them to visitors.

The safe production debugging setup

In wp-config.php, above the line /* That's all, stop editing! */:

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );          // write to wp-content/debug.log
define( 'WP_DEBUG_DISPLAY', false );     // don't show errors on pages
@ini_set( 'display_errors', 0 );

Reproduce the problem (load the broken page), then read the log:

tail -n 50 /var/www/example.com/wp-content/debug.log

Typical findings:

  • PHP Fatal error: Uncaught Error: Call to undefined function … in plugins/some-plugin/…: an incompatible or broken plugin;
  • Allowed memory size of … exhausted: raise the memory limit, or find the leak. See WordPress memory limit;
  • deprecation notices: usually harmless, but they tell you which plugin needs updating.

Keep debug.log private

wp-content/debug.log is publicly downloadable by default, and it can leak paths, queries and sometimes data. Either log somewhere outside the web root:

define( 'WP_DEBUG_LOG', '/var/log/wordpress/example-debug.log' );
sudo mkdir -p /var/log/wordpress && sudo chown www-data:www-data /var/log/wordpress

…or block it in Nginx:

location ~* /wp-content/debug\.log$ { deny all; }

See the ideal Nginx config for WordPress.

Other useful constants

Constant Purpose
SCRIPT_DEBUG Load unminified core CSS/JS (for script problems)
SAVEQUERIES Record database queries (performance cost; for development)
WP_DISABLE_FATAL_ERROR_HANDLER Disable the “critical error” screen and recovery mode emails (for development)
WP_ENVIRONMENT_TYPE production, staging, development or local: lets plugins adjust behaviour

When WordPress can’t even start: server logs

If PHP crashes before WordPress loads, debug.log may stay empty. Check the server logs:

sudo tail -n 50 /var/log/nginx/error.log
sudo journalctl -u php8.3-fpm --since "15 min ago"
sudo tail -n 50 /var/log/php8.3-fpm.log

Nginx’s error log shows PHP fatal errors passed through FastCGI (FastCGI sent in stderr: "PHP message: …"), timeouts (504), and permission problems. See Nginx access and error logs and journalctl.

Debug with WP-CLI

WP-CLI shows errors directly in the terminal:

wp plugin list                 # fatal errors appear here too
wp plugin deactivate --all     # isolate a plugin problem
wp theme activate twentytwentyfive
wp eval 'echo get_option("home");'

If WP-CLI itself crashes because of a plugin, skip loading plugins and themes:

wp --skip-plugins --skip-themes plugin deactivate broken-plugin

See WP-CLI guide.

Query Monitor for performance and errors

The Query Monitor plugin adds a toolbar panel (for administrators only) with PHP errors, slow database queries, HTTP API calls, hooks and conditionals, per page. It’s the best tool for finding what makes a page slow. Deactivate it when you’re done.

Recovery mode

For fatal errors, WordPress (5.2+) emails the admin a recovery mode link. It lets you log in with the broken plugin or theme paused, so you can deactivate it. If the email doesn’t arrive (mail not configured), use WP-CLI or rename the plugin’s folder via SSH:

mv wp-content/plugins/broken-plugin wp-content/plugins/broken-plugin.off

See WordPress critical error.

Turn it off afterwards

Leaving WP_DEBUG on in production fills the disk with notices, and slows things down slightly. Set it back:

define( 'WP_DEBUG', false );

…and delete or rotate the log file.

Quick reference

Goal Setting
Log errors, hide from visitors WP_DEBUG true, WP_DEBUG_LOG true, WP_DEBUG_DISPLAY false
Custom log path define('WP_DEBUG_LOG', '/var/log/…');
Server-level errors /var/log/nginx/error.log, PHP-FPM log
Isolate plugins wp plugin deactivate --all
Profile a page Query Monitor

Related: WordPress white screen of death and WordPress 500 error.

  • WordPress
  • Troubleshooting
  • PHP