RE:NODE

WordPress white screen and 500 error: how to fix them

By RE:NODE Team
19 min read


A blank page, a 500, "There has been a critical error on this website" and "Error establishing a database connection" look like four problems and are mostly two: PHP died while running your code, or PHP could not reach MySQL. The way to tell which is to stop guessing and read the error. Turn on WP_DEBUG_LOG in wp-config.php, reload the broken page once, and read wp-content/debug.log and your PHP error log. Nine times in ten the last line names a plugin or theme file and a reason. If it does not, work through the order in this post: rename the plugins folder, switch to a default theme, raise the memory limit, regenerate the rewrite rules, check the database credentials, and only then repair the database.

Everything below works with nothing but a file manager or SFTP, which is the position you are usually in when the dashboard is gone.

What each error actually means#

The browser shows you very little, and what it shows depends on how PHP failed. This table is the map for the rest of the post.

What you seeWhat happenedFirst place to look
Completely blank pageA fatal PHP error with display_errors offdebug.log, PHP error log
"There has been a critical error on this website"A fatal error, caught by WordPress 5.2 or laterRecovery mode email, debug.log
500 Internal Server ErrorThe web server or PHP gave up before sending a pageServer error log, .htaccess
"Allowed memory size ... exhausted"One request hit PHP's memory_limitmemory_limit, WP_MEMORY_LIMIT
"Error establishing a database connection"WordPress could not log in to MySQL, or MySQL is downDB_* constants in wp-config.php

The classic "white screen of death" is the oldest of these. Before WordPress 5.2, any fatal error in a plugin produced a page with nothing on it. Since then WordPress wraps most fatal errors, shows the "critical error" message and sends the administrator an email. A truly blank page today usually means one of three things: the error happened before WordPress could catch it (a syntax error in wp-config.php or in an early-loading file), the fatal error happened in the error handler itself, or PHP ran out of memory so completely that nothing could be printed.

A 500 is a different layer. It is a status code from the web server, and it says only "something failed on the server". PHP crashing produces a 500. So does a broken rewrite rule, a permissions problem, a request that exceeded a timeout, or a PHP process killed for using too much memory. That is why the first job is always the same: find the log line that goes with the failed request.

One more distinction saves time. If only the admin screens fail and the front end works, or the reverse, the fault is in code that loads on one side only - a theme template, a plugin's admin page, a widget. If everything fails, including a static file such as /readme.html, the problem is below WordPress: the server, the PHP version, or the file system. Request /readme.html and see whether it loads. If it does, the web server is fine and PHP or WordPress is at fault.

Turn on logging first: WP_DEBUG and debug.log#

Every fix in this post goes faster once you can read the real error. WordPress has three constants for this, all set in wp-config.php above the line that says That's all, stop editing!.

wp-config.php
define( 'WP_DEBUG', true );define( 'WP_DEBUG_LOG', true );define( 'WP_DEBUG_DISPLAY', false );@ini_set( 'display_errors', 0 );

What each one does:

  • WP_DEBUG turns on WordPress's own error reporting. Its default is false.
  • WP_DEBUG_LOG writes errors to wp-content/debug.log. It also accepts a path instead of true, if you would rather the log lived somewhere else.
  • WP_DEBUG_DISPLAY controls whether errors are printed into the page. Its default is true, which is why a debugging session on a live site can leak file paths to every visitor. Set it to false and read the log instead.

The @ini_set( 'display_errors', 0 ) line is belt and braces: WordPress's debug mode can otherwise enable display on hosts where PHP's own setting is on.

Now request the broken page once, then open wp-content/debug.log in the file manager. The lines you want look like this:

wp-content/debug.log
[16-Oct-2026 09:12:41 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function  gutenberg_get_block_template() in /wp-content/plugins/old-slider/slider.php:88[16-Oct-2026 09:12:41 UTC] PHP Fatal error:  Allowed memory size of 134217728 bytes  exhausted (tried to allocate 20480 bytes) in /wp-includes/class-wp-hook.php on line 324

Read the path, not the message. /wp-content/plugins/old-slider/ names the plugin. /wp-content/themes/mytheme/functions.php names the theme. A path inside /wp-includes/ or /wp-admin/ with a memory message usually means the victim, not the culprit: something earlier in the request used the memory, and core was the code that happened to be running when it ran out.

If debug.log never appears, the usual reasons are that wp-config.php was edited below the "stop editing" line (the constants must come before wp-settings.php is loaded), that wp-content is not writable by the PHP user, or that the error happens before WordPress starts at all. In the last case, the PHP error log is the only record.

Reading the PHP error log#

debug.log only contains what WordPress's handler saw. PHP's own error log is wider: it catches parse errors, fatal errors before WordPress boots, and warnings from extensions. Where it lives depends on the error_log directive in php.ini; if that is unset, errors go to the web server's error log or to the process's standard error.

Check from a script, since the answer differs per setup. Put this in a file, load it once, and delete it afterwards:

whereis-log.php
<?phpecho ini_get( 'error_log' ) ?: 'not set - using the server or stderr';echo "\n", ini_get( 'log_errors' ) ? 'log_errors on' : 'log_errors off';echo "\n", php_ini_loaded_file();

If you have a shell, tail the log while you reload the page:

bash
$ tail -f /path/to/php_errors.log

On a panel-based server the console is where the web server and PHP output appears, and the file manager is where any log file PHP writes to will be. The difference between a 500 with a PHP fatal in the log and a 500 with nothing in the PHP log is useful in itself. A fatal in the log means fix the code named in it. An empty PHP log and a 500 means the request never reached PHP, which points at the web server configuration, .htaccess or the process being killed. The general approach to logs is in game server logs explained, which is about game servers but the habit of reading from the bottom, matching timestamps to your own request, is the same. For PHP's logging settings in full, see php.ini settings that matter.

Disable plugins without the dashboard#

A plugin is the cause in most white screens, and you do not need the admin area to switch one off. WordPress only loads plugins from wp-content/plugins. Rename that folder and every plugin stops loading.

  1. Open the file manager or connect over SFTP (SFTP and the file manager covers the connection details).
  2. Rename wp-content/plugins to wp-content/plugins.off.
  3. Reload the site. If the error is gone, a plugin caused it.
  4. Rename the folder back to plugins. WordPress will show every plugin as deactivated, because it could not find them.
  5. Rename the folders inside plugins one at a time, or in halves, to find the guilty one. Activate the rest from the dashboard.

Renaming a single plugin's folder works the same way and is faster when debug.log already named it. Add -disabled to the end of the folder name, not a leading character, so you can see what you changed.

With WP-CLI, if you have a shell where it is installed, the same job is two commands and does not touch the files:

bash
$ wp plugin list --status=active$ wp plugin deactivate --all$ wp plugin activate woocommerce

If WP-CLI refuses to run because the broken plugin crashes WordPress on load, add --skip-plugins to any command: wp plugin deactivate --all --skip-plugins. There is a matching --skip-themes. We have not confirmed that every plan's console gives you a shell with WP-CLI in it, so treat the file manager route as the one that always works.

Two cautions. First, mu-plugins is a separate folder, called "must-use", and it loads whether or not anything is activated. Some hosts and caching plugins put a file there. If renaming plugins changes nothing, look in wp-content/mu-plugins and rename that folder too. Second, wp-content/advanced-cache.php and wp-content/object-cache.php are drop-ins left by cache plugins. They load before plugins do, and one pointing at a deleted plugin will crash everything. If the log names either file, rename it.

Switch to a default theme#

If the plugins are not the problem, the theme is next. A theme's functions.php runs on every request, and one mistake in it takes the whole site down, including wp-admin. The usual cause is an edit made in the theme editor, a theme update that needs a newer PHP version, or a child theme whose parent folder has been renamed.

Move the active theme's folder out of the way. In wp-content/themes, rename the broken theme, for example mytheme to mytheme-off. When WordPress cannot find the active theme it falls back to any default theme it does find, so you need one present: twentytwentyfive or whichever recent default is installed. If none is, upload one from wordpress.org by extracting the zip into wp-content/themes; the file manager unpacks archives in place.

With a shell and WP-CLI:

bash
$ wp theme list$ wp theme activate twentytwentyfive

Swap in the name of a default theme that is actually installed. After the switch, a working site tells you the fault was in the theme. A theme that fails only on one page type, such as single posts or the shop, points at the template file for that type; the path in debug.log will name it.

PHP memory: memory_limit and WP_MEMORY_LIMIT#

The message Allowed memory size of 134217728 bytes exhausted is the one error that names its own fix, though not always the right one. 134217728 bytes is 128 MB, which is the common default for PHP's memory_limit. The "tried to allocate" figure is the final straw, not the total. Four numbers interact:

SettingWhereDefault
memory_limitphp.ini or PHP pool config128M
WP_MEMORY_LIMITwp-config.php40M (64M on multisite)
WP_MAX_MEMORY_LIMITwp-config.php256M, used in admin
Container or plan memoryYour hostPlan RAM

WP_MEMORY_LIMIT is what WordPress asks PHP to allow for a front-end request. It can raise the limit only up to what the server allows, so setting it above memory_limit can fail silently if the host locks memory_limit with a pool-level setting. WP_MAX_MEMORY_LIMIT is the higher ceiling WordPress uses for admin tasks such as image resizing and updates.

wp-config.php
define( 'WP_MEMORY_LIMIT', '256M' );define( 'WP_MAX_MEMORY_LIMIT', '512M' );

If that changes nothing, raise memory_limit itself in php.ini, or in a .user.ini in the site root if your PHP runs under FPM or CGI:

.user.ini
memory_limit = 256M

.user.ini is cached for a few minutes, so wait before deciding it did not work. The long version of this, including why php_value lines in .htaccess cause a 500 under FPM, is in php.ini settings that matter.

Raising the limit is a plaster, not a fix, when something is leaking. A single page that needs more than 256 MB is almost always a plugin loading an enormous query result, a broken import, or a loop. If memory runs out at the same 128 MB or 256 MB mark no matter how high you set it, the log line's file path tells you who is doing it.

There is also a ceiling above PHP. On a container-based plan the process cannot use more than the plan's RAM, whatever memory_limit says. A memory_limit of 1 GB on a 1 GB plan with several requests in flight ends with the process killed, not with a tidy PHP message, and the visitor gets a 500 or a dropped connection with nothing in PHP's log. On RE:NODE, a server that reaches its memory limit is stopped by the kernel and restarts clean rather than swapping, and the console graphs show memory against the limit, so a sawtooth that hits the line and falls is the sign. How much RAM does WordPress need covers sizing by PHP worker, which is the right way to decide between raising a limit and buying a bigger plan.

A 500 with no PHP error behind it is nearly always the web server's configuration. What you do next depends on which web server your plan uses, and that varies by host. We do not state it for RE:NODE web plans, so the two cases are given separately.

If your plan uses Apache, or any server that reads .htaccess, that file is the usual suspect. A bad directive in it, such as a php_value line under PHP-FPM, a pasted rule for a module that is not loaded, or a stray character, produces a 500 for every request. Regenerate it:

  1. Rename .htaccess in the site root to .htaccess.bak. Hidden files may need a "show hidden files" toggle in the file manager.
  2. Reload the site. The front page may now work while posts return 404.
  3. In the dashboard, go to Settings, then Permalinks, and click Save without changing anything. WordPress writes a fresh file.

If you cannot reach the dashboard, create the file by hand with the standard WordPress block:

.htaccess
# BEGIN WordPress<IfModule mod_rewrite.c>RewriteEngine OnRewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]RewriteBase /RewriteRule ^index\.php$ - [L]RewriteCond %{REQUEST_FILENAME} !-fRewriteCond %{REQUEST_FILENAME} !-dRewriteRule . /index.php [L]</IfModule># END WordPress

With WP-CLI, wp rewrite flush --hard rewrites the file, provided it is writable.

If your plan uses nginx, there is no .htaccess to read, and the file is simply ignored. Pretty permalinks work through a try_files rule in the server configuration, and a missing one gives 404 on every URL except the home page, not a 500. Renaming .htaccess will not help you there.

A 500 that appears only on one action also has less obvious causes:

  • Timeouts. A page that takes longer than max_execution_time (default 30 seconds) dies with a PHP fatal. A longer wait at a reverse proxy gives a 502 or 504 instead. Import jobs and backup plugins hit this.
  • Permissions. WordPress needs to read everything and write to wp-content. On a container where one user owns everything this rarely bites, but a file uploaded by another user over SFTP can arrive with a mode PHP cannot read. SFTP cannot edit files: permission denied walks through that.
  • PHP version. A plugin written for PHP 7 can fatal on 8.3 or later. If the log shows "Unsupported operand types" or "Call to undefined function" for something old, check the plugin's supported versions before anything else.

WordPress core files and the critical error message#

"There has been a critical error on this website" is WordPress catching a fatal error and replacing the white screen with a message. The important part is that it also sends an email.

Recovery mode

WordPress emails the site administrator, using the address under Settings, then General, a message titled along the lines of "Your Site is Experiencing a Technical Issue". It names the plugin or theme at fault and carries a special login link. Following the link opens the dashboard in recovery mode, where the broken plugin or theme is paused for your session only. You can then deactivate it properly from the Plugins screen, and exit recovery mode.

Three practical points:

  • The link is valid for a limited time, one day by default, and WordPress sends at most one email per error type in that window, so a second reload will not produce a second email.
  • The email goes to the admin address. If that address is a mailbox you no longer use, or your site cannot send mail, you will never see it.
  • A site that cannot deliver mail is common. If the email never arrives, do not wait for it. The plugin and theme renames above do the same job.

To send the email somewhere else, define RECOVERY_MODE_EMAIL in wp-config.php:

wp-config.php
define( 'RECOVERY_MODE_EMAIL', 'you@example.com' );

Damaged core files

If the log names a file in wp-includes or wp-admin, or reports a missing class that core should define, the WordPress files themselves may be damaged - a failed update, an interrupted upload, or malware. The fix is to put the core files back without touching your content.

With WP-CLI:

bash
$ wp core verify-checksums$ wp core download --force --skip-content

verify-checksums compares your core files with the official ones. --force overwrites core and --skip-content leaves wp-content alone. Without WP-CLI, download the same version from wordpress.org, extract it, and upload wp-admin and wp-includes over the existing ones, plus the loose files in the root except wp-config.php. Never upload over wp-content and never delete it; that folder holds your uploads, themes and plugins. A site that fails the checksum check with unexplained extra files in core folders has a different problem, and what to do when your server is hacked is the place to continue. Hardening to prevent a repeat is in WordPress security hardening.

Error establishing a database connection#

This error comes from WordPress, not PHP, and it means one thing: the call to connect to MySQL failed. It has four causes, and the order to check them is fast to slow.

  1. Wrong credentials in `wp-config.php`. Most common after a migration, a password change or a restore.
  2. The database server is down or unreachable.
  3. The database is out of connections or resources.
  4. Corrupt tables.

Start with the file. Four constants decide the connection:

wp-config.php
define( 'DB_NAME', 'wp_site' );define( 'DB_USER', 'wp_user' );define( 'DB_PASSWORD', 'the-generated-password' );define( 'DB_HOST', 'localhost' );

Compare each against the real values. On a RE:NODE web plan, the database slot is created in the panel with a generated host, user, database name and password, and the WordPress line writes wp-config.php for a MySQL database of its own, so the file should already match. If it does not, the panel's database section is the source of truth - copy from it, not from memory. A trailing space or a quote lost in a paste is enough to fail. DB_HOST is not always localhost: a database on another host needs that host's name, and a non-default port is written host:3307.

The panel's "Open in phpMyAdmin" button is the quickest test of whether the database is alive. It signs you in with a one-use token that expires in 60 seconds. If phpMyAdmin opens and shows your tables, the server is up and the fault is the credentials or the host value in wp-config.php. If it will not open, the database slot is the problem, and a support ticket from the panel is the next step.

From a shell with the MySQL client you can test the same details directly:

bash
$ mysql -h HOST -u USER -p DATABASE -e "SELECT 1;"

If that works and WordPress still cannot connect, something in the PHP layer differs, such as a missing mysqli extension, which php -m will show. mysqli vs PDO explains how PHP talks to MySQL and which drivers matter. If the failure is intermittent, with the site working and then failing under load, the database is out of connections, and MySQL connection limits and pooling covers that case.

One variant is worth separating. If the front end shows the database error but /wp-admin shows "One or more database tables are unavailable. The database may need to be repaired", the credentials are right and the tables are damaged.

Repairing the database#

WordPress has a built-in repair tool, disabled by default because it needs no login. Enable it by adding one line to wp-config.php:

wp-config.php
define( 'WP_ALLOW_REPAIR', true );

Then visit /wp-admin/maint/repair.php on your site. It offers two buttons: Repair Database, and Repair and Optimise Database. Run the first. When it finishes, remove the line at once.

The alternatives:

bash
$ wp db check$ wp db repair

or, in phpMyAdmin, tick the damaged tables and choose Repair table from the dropdown beneath the list. Note that REPAIR TABLE works on MyISAM tables; for InnoDB, which is the default for current WordPress, repair does little and the real remedy is a restore from backup. mysqldump backup and restore shows how to export before you touch anything, and database backups and restores is the wider routine.

Before a repair, the panel's backups are the safety net. Backups on RE:NODE can be taken on demand, are stored off the machine they protect, and are restored with a button. Take one before you rename folders, edit wp-config.php, or run a repair, and you can always return to where you started. A backup nobody has restored is a hypothesis, so see testing a restore before you need it.

A safe order of operations#

When the site is down and you are tempted to change five things at once, change one at a time and test between each. This is the order that costs least and risks least:

  1. Request /readme.html to see whether the server answers at all.
  2. Enable WP_DEBUG_LOG with WP_DEBUG_DISPLAY off, reload, and read debug.log and the PHP error log.
  3. Take a backup if you are about to change files or the database.
  4. Rename wp-content/plugins (and mu-plugins if needed).
  5. Rename the active theme folder.
  6. Raise WP_MEMORY_LIMIT, then memory_limit.
  7. Rename .htaccess and resave permalinks, if your plan uses Apache.
  8. Check DB_NAME, DB_USER, DB_PASSWORD and DB_HOST against the panel.
  9. Verify or replace core files.
  10. Repair the database as the last resort.

When something works, put things back one at a time. Restore the plugin folder, then re-enable plugins in halves. It is tempting to leave the site running on a default theme and no plugins, and that is how sites quietly lose features for months. Finally, turn debugging off and delete debug.log.

Prevention is cheap. Update on a staging copy first (running a test server beside production describes the habit), keep a recent backup before every plugin update, and do not edit theme files in the dashboard editor. The editor has no undo and no syntax check on older setups, and one missing semicolon is a white screen.

FAQ#

Why does my site show a white screen but no error?

Because display of errors is off, which is correct for a live site. The error exists but it is in a log. Set WP_DEBUG and WP_DEBUG_LOG to true and WP_DEBUG_DISPLAY to false, reload once, and read wp-content/debug.log. If the log stays empty, check the PHP error log, since the failure may be before WordPress started.

Is a 500 error my host's fault?

Sometimes, but rarely. Most 500s on WordPress are a plugin, a theme, a bad .htaccess rule or a memory limit. Try the plugin rename and the log first. If the PHP log is empty, /readme.html fails too, and nothing you changed matches, a ticket to the host is reasonable. RE:NODE tickets from the panel reach all staff.

How much should I raise the memory limit?

To 256M first. If the error persists at 256M, find out what is using the memory instead of raising it again. Memory exhausted at every limit you try means a loop or an oversized query, not a small limit. A limit above the plan's RAM only moves the failure from PHP's tidy message to the process being killed.

I did not receive the recovery mode email. What now?

Check the administrator address under Settings, then General, and look in spam. A site that cannot send mail cannot send this either. Rename the plugins folder instead; it does the same job. Set RECOVERY_MODE_EMAIL in wp-config.php so the next one goes somewhere you read.

Will renaming the plugins folder delete my settings?

No. Plugin settings live in the database, and renaming only stops WordPress loading the code. When you rename the folder back, the plugins appear deactivated and you reactivate them. A few plugins reset an option when deactivated, so take a backup before the test.

Do I need WP-CLI to fix any of this?

No. Every step has a file manager or SFTP route, and the panel's phpMyAdmin button covers the database. WP-CLI is faster when you have a shell with it installed, and --skip-plugins lets it work even when a plugin breaks WordPress on load.

Was this helpful?