← Back to Blog

PHP White Screen of Death: Complete Troubleshooting Guide for 2026

You just deployed code, refreshed your browser, and got... nothing. A completely blank white page. No error, no stack trace, no clue what went wrong. Welcome to the PHP White Screen of Death. Let us fix it.

TL;DR - Check Error Logs First

Before you change anything, check your error logs. The answer is almost always already there:

# Apache error log
tail -f /var/log/apache2/error.log

# Nginx error log
tail -f /var/log/nginx/error.log

# PHP-FPM log
tail -f /var/log/php-fpm/error.log

# PHP-FPM (Ubuntu/Debian with versioned PHP)
tail -f /var/log/php8.2-fpm.log

If you cannot access the server, add this to the top of your PHP file temporarily: ini_set('display_errors', 1); error_reporting(E_ALL);

What Is the PHP White Screen of Death?

The PHP White Screen of Death (WSOD) is exactly what it sounds like: a completely blank white page in your browser. No error message, no HTML output, nothing. It happens when PHP encounters a fatal error but has error display turned off, which is the default behavior on most production servers.

The reason this is so frustrating is that PHP is intentionally hiding the error from you. In production, display_errors is set to Off to prevent leaking sensitive information (like file paths, database credentials, or server internals) to end users. That is a good security practice. But it means when something breaks, you are staring at a blank page wondering what on earth happened.

The good news is that the WSOD is almost always caused by one of about eight common issues. Let us walk through every single one.

The 8 Most Common Causes of PHP WSOD

Here is what triggers a white screen in PHP, ranked roughly by how often I see each one in the wild:

  1. Error display is disabled - The error happened, but PHP is hiding it from you
  2. PHP memory limit exhausted - Your script ran out of memory and PHP killed it
  3. PHP syntax error - A typo in your code prevents PHP from parsing the file at all
  4. OPcache serving stale bytecode - Cached code from a previous deployment is conflicting with new code
  5. .htaccess corruption or bad rewrite rules - Apache cannot process the request
  6. Plugin or module conflicts - Two extensions are stepping on each other
  7. PHP version incompatibility - Code written for PHP 7.x running on PHP 8.x (or vice versa)
  8. File permission issues - PHP cannot read the files it needs to execute

Step-by-Step Fix for Each Cause

1. Enable Error Display

This is always your first step. You cannot fix what you cannot see. There are several ways to turn on error display depending on your level of access:

Option A: Edit php.ini (recommended for development)

# Find your php.ini location
php --ini

# Edit the file and set:
display_errors = On
error_reporting = E_ALL
log_errors = On
error_log = /var/log/php_errors.log

Restart your web server or PHP-FPM after changing php.ini:

# Apache with mod_php
sudo systemctl restart apache2

# PHP-FPM
sudo systemctl restart php8.2-fpm

Option B: Use .htaccess (Apache with mod_php only)

php_flag display_errors on
php_value error_reporting E_ALL

Option C: Use .user.ini (PHP-FPM)

Create a .user.ini file in your web root:

display_errors = On
error_reporting = E_ALL

Note that .user.ini files are cached for 300 seconds by default (user_ini.cache_ttl), so changes will not take effect immediately.

Option D: Add it directly to the PHP file

<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
// ... rest of your code

Pro Tip: You can see the error without changing any config file at all. Run this from the command line:

php -d display_errors=1 -r "require 'index.php';"

This runs your file with error display enabled for just that single execution. No config changes, no restarts. This is my go-to when debugging on production where I do not want to touch any settings.

2. Check and Increase Memory Limit

PHP has a per-script memory limit (usually 128MB or 256MB). When your script exceeds it, PHP kills the process and you get a white screen. The error log will show something like:

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 65536 bytes)

Check your current limit:

php -r "echo ini_get('memory_limit');"

Increase it in php.ini:

memory_limit = 512M

Or temporarily in your script:

ini_set('memory_limit', '512M');

But hold on. Before you just throw more memory at it, ask yourself why the script needs that much memory. Common culprits include loading an entire database table into an array, processing large images without streaming, recursive functions without a termination condition, and memory leaks in long-running loops. Increasing the limit is a bandaid. The real fix is optimizing your code. For a deep dive on this specific issue in Magento, check out our Magento PHP memory exhaustion guide.

3. Check for Syntax Errors

A syntax error prevents PHP from parsing the file at all. If the error is in the same file where you set display_errors, you will still get a white screen because PHP cannot even read the display_errors directive.

Use the lint flag to check for syntax errors without executing the file:

# Check a single file
php -l index.php

# Check all PHP files in a directory
find . -name "*.php" -exec php -l {} \; 2>&1 | grep -v "No syntax errors"

Common syntax errors that cause WSOD:

  • Missing semicolons
  • Unclosed brackets, parentheses, or quotes
  • Using PHP 8 syntax (named arguments, match expressions, union types) on a PHP 7 server
  • Stray characters after a closing ?> tag (especially BOM characters)

4. Clear OPcache

OPcache stores compiled PHP bytecode in shared memory so PHP does not have to parse and compile the same files on every request. This is great for performance. But it can cause real problems after deployments.

Here is the scenario: you deploy new code, but OPcache is still serving the old compiled bytecode. If the new code changed a class structure, added or removed a function, or modified method signatures, the stale cache can cause fatal errors that show up as a white screen.

# Check if OPcache is enabled
php -r "echo opcache_get_status() ? 'OPcache ON' : 'OPcache OFF';"

# Clear OPcache by restarting PHP-FPM
sudo systemctl restart php8.2-fpm

# Or create a temporary PHP file to reset it
# (because CLI and web have separate OPcache pools)
<?php
opcache_reset();
echo "OPcache cleared";

For your deployment pipeline, always include an OPcache reset step. If you are using PHP-FPM, a graceful reload (kill -USR2 on the master process) will clear the cache without dropping connections.

5. Fix .htaccess Issues

A corrupted or misconfigured .htaccess file can cause Apache to return a 500 error, which sometimes renders as a blank white page (especially if your custom error pages are also broken).

Test by temporarily renaming .htaccess:

mv .htaccess .htaccess.bak

If the site loads after removing .htaccess, the problem is in that file. Common .htaccess issues:

  • Using directives that require modules that are not loaded (like mod_rewrite)
  • Infinite rewrite loops
  • php_value directives when running PHP-FPM (these only work with mod_php)
  • Encoding issues (BOM characters at the start of the file)

Check Apache's error log for .htaccess related errors:

grep -i "htaccess\|rewrite\|AllowOverride" /var/log/apache2/error.log | tail -20

6. Resolve Plugin and Module Conflicts

If you are running a CMS or framework, a newly installed or updated plugin can crash the entire application. The approach here is systematic isolation:

  1. Check the error log first (always step one)
  2. If the error points to a specific plugin file, disable that plugin
  3. If the error is not clear, disable all plugins and re-enable them one at a time
  4. Check if the issue started after a recent update (check git log or deployment history)

For framework-specific plugin debugging, see the WordPress, Laravel, and Magento sections below.

7. Fix PHP Version Incompatibility

PHP 8.0 and above introduced breaking changes that will cause white screens if your code was written for PHP 7.x. The most common issues:

  • Named arguments conflict: PHP 8.0+ supports named arguments, but libraries calling internal functions with different parameter names will break
  • Null handling: PHP 8.0 is stricter about passing null to non-nullable parameters
  • match vs switch: Not a WSOD cause itself, but related type mismatches can be
  • Removed functions: Functions like create_function(), each(), and mysql_* were removed in PHP 8.0
  • Union types and readonly properties: Code using PHP 8.1+ features will fail on PHP 8.0 or 7.x

Check which PHP version is running:

php -v
# Also check what the web server is actually using (may differ from CLI)
php -r "phpinfo();" | grep "PHP Version"

Use the PHP compatibility checker to scan your codebase:

composer global require phpcompatibility/php-compatibility
phpcs --standard=PHPCompatibility --runtime-set testVersion 8.2 /path/to/code

8. Fix File Permission Issues

PHP needs to read your files to execute them. If the web server user (typically www-data on Ubuntu or apache on CentOS) does not have read permissions on your PHP files, you get a white screen.

# Check ownership and permissions
ls -la /var/www/html/index.php

# Fix ownership (Ubuntu/Apache)
sudo chown -R www-data:www-data /var/www/html

# Fix permissions (directories: 755, files: 644)
sudo find /var/www/html -type d -exec chmod 755 {} \;
sudo find /var/www/html -type f -exec chmod 644 {} \;

Also check if SELinux is blocking access (common on CentOS/RHEL):

# Check SELinux status
getenforce

# Check for SELinux denials
sudo ausearch -m avc -ts recent

# If SELinux is blocking, set the correct context
sudo chcon -R -t httpd_sys_content_t /var/www/html

Apache vs Nginx: Error Log Locations and Debugging Differences

Where you look for errors depends on your web server and PHP setup. Here is a quick reference:

ComponentApacheNginx
Web server error log/var/log/apache2/error.log/var/log/nginx/error.log
Virtual host logDefined in ErrorLog directiveDefined in error_log directive
PHP error logSame as Apache log (mod_php) or separate (PHP-FPM)Always separate (PHP-FPM required)
PHP-FPM pool log/var/log/php-fpm/www-error.log/var/log/php-fpm/www-error.log
PHP handlermod_php or PHP-FPMPHP-FPM only (Nginx cannot run mod_php)
.htaccess supportYes (with AllowOverride)No (use .user.ini instead)
Reload PHP configsystemctl restart apache2 (mod_php) or restart php-fpmsystemctl restart php8.2-fpm
502 Bad GatewayRare (mod_php runs in-process)Common (means PHP-FPM crashed or is unreachable)

One key difference: with Apache and mod_php, a PHP fatal error shows up directly in the Apache error log. With Nginx (which always uses PHP-FPM), you might see a generic 502 Bad Gateway in the Nginx log while the actual PHP error is in the PHP-FPM log. Always check both. For more on Nginx 502 errors, see our Nginx 502 Bad Gateway troubleshooting guide.

Laravel WSOD Specifics

Laravel has its own flavor of the white screen. The framework's error handler catches exceptions and renders a nice error page, but if the error handler itself fails, you get a WSOD. Here are the Laravel-specific fixes:

Storage Permissions

Laravel needs write access to the storage/ and bootstrap/cache/ directories. Without it, the framework cannot write logs, cache compiled views, or store session data:

sudo chmod -R 775 storage bootstrap/cache
sudo chown -R www-data:www-data storage bootstrap/cache

Enable Debug Mode

Set APP_DEBUG=true in your .env file to see the full stack trace. Never leave this on in production.

# .env
APP_DEBUG=true
APP_ENV=local

Clear All Caches

Laravel caches routes, config, views, and events. A stale cache after a deployment is a very common WSOD trigger:

php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear
php artisan event:clear

# Nuclear option: clear everything
php artisan optimize:clear

Check the Laravel Log

tail -f storage/logs/laravel.log

If the log file does not exist or is empty, the problem is almost certainly a permissions issue on the storage/logs/ directory.

Magento WSOD Specifics

Magento is particularly prone to the WSOD because of its complex compilation and deployment process. If you are running Magento 2 and hit a white screen, here is where to look:

Check Deploy Mode

php bin/magento deploy:mode:show

If you are in production mode, Magento will not display errors at all. Switch to developer mode for debugging:

php bin/magento deploy:mode:set developer

Clear Generated Files

Magento compiles dependency injection configuration and generates interceptors (plugins). If these compiled files are stale or corrupted, you get a WSOD:

# Remove generated code
rm -rf generated/code generated/metadata

# Recompile
php bin/magento setup:di:compile

# Clear cache
php bin/magento cache:flush

Memory for di:compile

The di:compile command is extremely memory-hungry. On a Magento instance with 200+ modules, you need at least 4GB:

php -d memory_limit=4G bin/magento setup:di:compile

If you hit a WSOD right after running setup:upgrade or di:compile, memory exhaustion during compilation is the most likely cause. See our detailed Magento memory exhaustion guide for tuning recommendations.

Static Content

Missing static content (CSS, JS) will not cause a true WSOD, but it can make the page appear blank because no styles are loaded. Run:

php bin/magento setup:static-content:deploy -f

WordPress WSOD Specifics

WordPress has dealt with WSOD since its early days and has built-in tools to help. Here is the WordPress-specific approach:

Enable WP_DEBUG

Add these lines to wp-config.php:

define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);

This writes errors to wp-content/debug.log without showing them to visitors. Check that file:

tail -f wp-content/debug.log

Deactivate Plugins via CLI

If you cannot access the admin panel, use WP-CLI to deactivate all plugins:

# Deactivate all plugins
wp plugin deactivate --all

# If that fixes it, reactivate one at a time
wp plugin activate plugin-name

If you do not have WP-CLI, you can rename the wp-content/plugins directory via FTP or SSH, which forces WordPress to deactivate everything:

mv wp-content/plugins wp-content/plugins.bak

Switch to Default Theme

If the WSOD persists after disabling plugins, the active theme might be the problem:

wp theme activate twentytwentyfive

Or rename your active theme's directory to force WordPress back to a default theme.

WordPress Recovery Mode

Since WordPress 5.2, if a fatal error occurs, WordPress sends an email to the admin with a special recovery link. Check your admin email inbox. The recovery link lets you log into the admin panel with the problematic plugin or theme automatically paused.

Prevention: Stop WSOD Before It Happens

Fixing a WSOD is reactive. Here is how to prevent them proactively:

  • Always test in staging first. Never deploy directly to production without testing in an environment that mirrors your production stack (same PHP version, same extensions, same memory limits).
  • Use CI/CD with syntax checking. Add php -l to your CI pipeline so syntax errors never make it to production.
  • Monitor error logs. Set up log aggregation (ELK stack, Datadog, CloudWatch) and alert on PHP fatal errors. You should know about a WSOD before your users tell you.
  • Set reasonable memory limits. Do not set memory_limit = -1 (unlimited). That masks memory leaks and will eventually crash your server. Set it to the maximum your application actually needs (usually 256MB-512MB for most apps, up to 4GB for Magento di:compile).
  • Include OPcache reset in deployments. Every deploy script should flush OPcache. For zero-downtime deploys, use opcache.validate_timestamps=0 with an explicit reset, not timestamp-based revalidation.
  • Version-pin PHP. Specify the exact PHP version in your deployment configs (Docker, Ansible, etc.). An unexpected PHP minor version bump can introduce subtle breaking changes.
  • Back up before changes. Always back up your files and database before major updates. If a WSOD happens, you can roll back in minutes instead of hours.
  • Scan your site for exposed error pages. Use the SecureBin Exposure Checker to verify that your production site is not leaking phpinfo, debug output, or error messages to the public.

6 Common Mistakes When Debugging WSOD

Mistake 1: Leaving display_errors On in production.

Turning on display_errors to debug is fine. Forgetting to turn it off is a security vulnerability. Error messages can reveal file paths, database names, and framework versions to attackers.

Mistake 2: Setting memory_limit to -1 (unlimited).

This does not fix the problem. It masks it. A memory leak will eventually consume all available RAM and crash your server or trigger the OOM killer, taking down other processes too.

Mistake 3: Editing the wrong php.ini file.

PHP often has separate ini files for CLI, Apache, and FPM. Use php --ini for CLI and check phpinfo() output for the web-facing php.ini. They are frequently in different locations.

Mistake 4: Not checking if PHP-FPM actually restarted.

Running systemctl restart php8.2-fpm and assuming it worked. Always verify: systemctl status php8.2-fpm. If the config has a syntax error, FPM will fail to start and you will get a 502 instead.

Mistake 5: Blaming the web server when it is a PHP issue.

A white screen is almost always PHP, not Apache or Nginx. The web server successfully handled the request and passed it to PHP. PHP is the one that returned nothing. Start debugging in PHP logs, not web server logs.

Mistake 6: Ignoring the PHP-FPM slow log.

If your WSOD is intermittent (works sometimes, blank sometimes), enable the PHP-FPM slow log. It records the stack trace of any request that takes longer than a threshold, which helps identify timeout-related white screens:

# In your PHP-FPM pool config (www.conf)
slowlog = /var/log/php-fpm/slow.log
request_slowlog_timeout = 5s

Is Your Site Leaking Error Details?

A misconfigured PHP setup can expose error messages, stack traces, and server paths to the public. Run a free scan to check if your site is leaking sensitive debug information.

Scan Your Website Free

Frequently Asked Questions

Why does PHP show a blank white page instead of an error message?

PHP hides errors by default in production because display_errors is set to Off in php.ini. When a fatal error occurs, PHP terminates execution but has nothing to display since error output is suppressed. The error is still logged to the PHP error log file. To see the actual error, check your error log with tail -f /var/log/php-fpm/error.log or temporarily enable display_errors in your php.ini or .htaccess file. You can also use the CLI trick: php -d display_errors=1 -r "require 'index.php';" to see the error without changing any configuration.

How do I fix the WSOD without access to the server command line?

If you only have FTP or file manager access, create or edit a .htaccess file in your web root and add: php_value display_errors 1 and php_value error_reporting E_ALL. This works on Apache with mod_php. For PHP-FPM setups, create a .user.ini file in your web root with the same directives (display_errors = On and error_reporting = E_ALL). You can also create a standalone PHP test file with error_reporting(E_ALL) and ini_set('display_errors', 1) followed by a require of your main index file to diagnose the issue without changing global configuration.

Can OPcache cause the PHP white screen of death?

Yes, and it is more common than most people realize. OPcache stores compiled PHP bytecode in shared memory. If you deploy new code but OPcache still serves the previously cached version, you can get fatal errors from mismatched class definitions, missing functions, or incompatible method signatures. This is especially common in environments without automated OPcache clearing in the deployment pipeline. The fix is to restart PHP-FPM (which fully clears OPcache), call opcache_reset() from a PHP script accessible via the web, or set opcache.validate_timestamps=1 with a short opcache.revalidate_freq during development. In production, always include opcache_reset() as part of your deployment script.

The Bottom Line

The PHP White Screen of Death looks scary, but it is almost always one of the eight causes listed above. Your debugging workflow should be: check the error log first, enable error display if needed, then work through the causes systematically. Do not guess. Do not randomly change settings. Read the error message, understand it, and fix the root cause.

The single best habit you can build is checking error logs before doing anything else. I have seen developers spend hours toggling settings and restarting services when the answer was sitting right there in /var/log/php-fpm/error.log the entire time.

Related guides: Nginx 502 Bad Gateway Fix, Magento PHP Memory Exhaustion Fix. Related tools: Exposure Checker, SSL Checker, DNS Lookup, and 70+ more free tools.

UK
Written by Usman Khan
DevOps Engineer | MSc Cybersecurity | CEH | AWS Solutions Architect

Usman has 10+ years of experience securing enterprise infrastructure, managing high-traffic servers, and building zero-knowledge security tools. Read more about the author.