WordPress white screen of death fix: catching ignored errors
- 3 Min. Read.
When developing a widget for SiteOrigin’s Page Builder I stumbled upon the well-known WordPress white screen of death, although error reporting was on & WP_DEBUG was set to true.
I tried registering my own error handlers, but still no output was getting generated. Instinctively, I took a look at the SiteOrigin_Widget class, and noticed an interesting line:
1 2 3 |
if( !empty($template_file) && file_exists($template_file) ) { @ include $template_file; } |
Notice the @ sign before including the template file. This @-sign is an error control operator (there is only 1 in PHP) and when you prepend @ before an expression in PHP, it mutes every error that will occur. The PHP documentation also features a big warning, which states the following:
For production environments, this is desired behaviour, but for development environments we kinda like to see those errors show up. When I manually removed the @ sign, my error would finally show, but this was just a temporary solution. I didn’t want to make lasting changes to the plugin (as they would be overridden when the plugin updated).
Introducing the white screen of death killer: register_shutdown_function
To avoid making changes to the plugin, I ended up registering my own shutdown handler in my functions.php file.
1 2 3 4 |
function my_shutdown_function() { // handle shutdown } register_shutdown_function( 'my_shutdown_function' ); |
A shutdown handler will execute after script execution finishes or exit() is called. It also gets called when nothing is wrong, so we have to check if there are any errors within this function. If there are errors, we output them to the screen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// Get the last occurred error $error = error_get_last(); // If we have an error if( $error !== NULL) { // Get the values $errno = $error['type']; $errfile = $error['file']; $errline = $error['line']; $errstr = $error['message']; // Echo the error echo 'Shutdown handler registered an error: ' . $errno . ': ' . $errstr . ', in file ' . $errfile . ' on line ' . $errline; } |
This shutdown handler will output the following when an error occurred:
This would probably be a good time to say that you’d be best off if you wrapped the registering of the shutdown handler in a conditional statement. Check whether or not WP_DEBUG is set to true (we don’t want to output errors on production now do we?), and only register the shutdown handler when it’s true. Note the 4 in our output, which is stored in the $errno variable (or $error['type'] ). This can be mapped to a predefined constant with a simple switch statement.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
switch ( $errno ) { case E_STRICT: case E_NOTICE: case E_DEPRECATED: case E_USER_NOTICE: $type = 'notice'; break; case E_WARNING: case E_USER_WARNING: $type = 'warning'; break; case E_PARSE: $type = 'Compile-time parse error'; break; default: $type = 'fatal error'; break; } |
Now whenever a white screen of death occurs, I can be assured my error will be caught by the shutdown_handler, even if it got muted in the first place!