Guide
WordPress fatal error — how to find what crashed your site
1. Problem
You hit your homepage and get a white screen, a generic "There has been a critical error on this website" message, or a hard HTTP 500. Admin is locked out the same way. You refresh — same thing. This is a WordPress fatal error, and right now your site is crashed.
The dashboard cannot help you because the dashboard is the thing that crashed. Uptime monitors will only tell you the page returned 500. Your hosting panel shows the PHP process restarting cleanly. Everything looks "fine" except that nothing works. You searched "php fatal error wordpress how to find" because the visible interface gave you nothing usable.
What you actually need is the line of PHP that died, the file it died in, and the plugin or theme that shipped that file. That information exists. It is sitting in a log file on the server right now. The rest of this guide is how to get to it fast, why WordPress hides it from you, and how to make sure the next fatal does not stay invisible for hours.
2. Impact
A fatal error is not a slow page or a styling glitch. PHP execution stops. The response WordPress sends is either a blank document, a generic critical-error page, or a 500 from the web server. From the user's perspective the site is gone.
Concrete impact:
- Revenue loss. Every minute of WSOD on a checkout, booking, or lead form is money on the floor. WooCommerce stores see this most painfully — abandoned carts on a crashed site never come back.
- SEO damage. Googlebot crawling during the outage records 5xx responses. Sustained 5xx leads to soft de-indexing of the affected URLs.
- Security drift. A fatal triggered by a security update that you then roll back leaves you on a vulnerable version. A fatal that masks a corrupted plugin file may itself be the symptom of a compromise.
- Trust. Repeat visitors who hit a broken site twice rarely come back a third time.
The cost of the outage is almost never the fix itself. It is the time between "the site crashed" and "I know which file to touch." That gap is what we are closing.
3. Why It’s Hard to Spot
The reason "wordpress site crashed" is such a panicked search is that WordPress is structurally bad at telling you about its own failures.
- The admin UI is the failure surface. When wp-admin itself fatals, there is no dashboard to read.
- The "critical error" email is unreliable. WordPress 5.2+ tries to email the site admin when a fatal happens. It uses
wp_mail, which itself runs through PHP. If the fatal happens early in the bootstrap, no email goes out. If your site uses an SMTP plugin and that plugin is the thing that crashed, no email goes out. In practice, expect to receive these emails maybe half the time. - Uptime checks see only the surface. Pingdom, UptimeRobot, and most hosting "site is up" checks observe HTTP status. A 500 looks identical whether it is a database glitch, a memory crash, a fatal in a single plugin, or a misconfigured cache.
WP_DEBUGis off in production. Debug mode would print the error to the screen, but you should never run production withWP_DEBUG_DISPLAY = true. So the fatal is logged to a file you have to know exists and have shell access to read.- Hosting panels normalize the symptom. Most managed hosts show "PHP errors: 12 today" without surfacing the message. You see a count but not the cause.
The result: a WordPress fatal error is a silent failure by default. It is loud to your users and silent to you.
4. Cause
A WordPress fatal error is a PHP fatal error. The PHP interpreter encountered a condition it cannot recover from inside a request, terminated execution mid-response, and wrote a final entry to the PHP error log. In Logystera terms, that terminal write is a php.fatal signal.
The most common conditions that produce a php.fatal:
- Uncaught Error — calling an undefined function, method, or class. After a plugin or theme update, this almost always means one piece of code expects a function that another piece of code no longer provides.
- Allowed memory size exhausted — the PHP process tried to allocate more memory than
memory_limitpermits. Often correlated with image processing, large queries, or a runaway loop in a recently updated plugin. - Maximum execution time exceeded — a request ran past
max_execution_time. Common with slow external API calls or unbatched cron work running in-request. - Type errors — passing a
nullwhere an object is expected. PHP 8 turns several previously-tolerated mistakes into fatals; sites that upgraded PHP without testing every plugin meet these immediately.
A php.fatal signal does not mean "WordPress is unhealthy." It means a specific request died at a specific line in a specific file and PHP wrote that fact to disk. The signal carries the message, the file path, the line number, and the stack. That is the diagnostic core of this entire guide.
5. Solution
5.1 Diagnose (logs first)
This is the part that matters. Every step here ties back to the php.fatal signal, because that is the only piece of evidence that names the failing code.
1. Find the PHP error log
The exact path depends on your stack. The common locations:
- PHP-FPM (most managed hosts, nginx setups):
/var/log/php-fpm/www-error.log,/var/log/php8.x-fpm.log, or per-pool under/var/log/php-fpm/.log - Apache + mod_php:
/var/log/apache2/error.logor/var/log/httpd/error_log - WordPress own debug log (if
WP_DEBUG_LOG = true):wp-content/debug.log - cPanel:
~/logs/error_logorpublic_html/error_log - WP Engine, Kinsta, Pressable: a "PHP error log" tab in their UI, surfacing the same file
If you do not know which one your stack uses, run:
php -i | grep -E 'error_log|log_errors'
That tells you exactly where PHP is writing.
2. Pull the most recent php.fatal entries
Once you have the path, this single grep is the fastest path to the culprit:
grep -i "PHP Fatal error" /var/log/php-fpm/www-error.log | tail -20
Each match is one php.fatal signal. A real one looks like this:
[27-Apr-2026 14:02:11 UTC] PHP Fatal error: Uncaught Error: Call to undefined function wp_get_current_user() in /var/www/html/wp-content/plugins/some-cache-plugin/inc/loader.php:142
Stack trace:
#0 /var/www/html/wp-settings.php(442): SomeCachePlugin\Loader->bootstrap()
#1 /var/www/html/wp-config.php(95): require_once('/var/www/html/wp-...')
#2 {main}
thrown in /var/www/html/wp-content/plugins/some-cache-plugin/inc/loader.php on line 142
That single entry tells you everything: the message (Call to undefined function), the file (some-cache-plugin/inc/loader.php), the line (142), and the stack that led there. The plugin slug in the path is your suspect.
3. Filter for the specific failure mode
If you need to narrow further:
# Memory exhaustion — produces memory_near_limit then php.fatal
grep "Allowed memory size" /var/log/php-fpm/www-error.log | tail -10
# Timeout fatals
grep "Maximum execution time" /var/log/php-fpm/www-error.log | tail -10
# Type errors common after PHP 8 upgrades
grep -E "TypeError|must be of type" /var/log/php-fpm/www-error.log | tail -10
Each grep maps to a different php.fatal sub-pattern. The "Allowed memory size" line is preceded in time by memory_near_limit warnings if you have them enabled — which is usually how you catch the cause before the crash next time.
4. Correlate with the 5xx in the web server log
The same fatal also leaves a fingerprint in the web server access log. To tie a specific request to a specific fatal, grep nginx for 5xx around the same timestamp:
awk '$9 ~ /^5/' /var/log/nginx/access.log | tail -20
Each 5xx here is a http.request signal that your php.fatal produced. The URL tells you which page the user was on when the crash happened — often the same page where the broken plugin runs (e.g., a cart page for a checkout plugin).
5. Check what changed
Plugin/theme updates are the single most common cause of a fresh fatal. To see what touched the site recently:
ls -lt wp-content/plugins/*/*.php | head -30
ls -lt wp-content/themes/*/*.php | head -10
Or, if you have WP-CLI:
wp plugin list --status=active --fields=name,version,update --format=table
Recent file modification times correlate to the wp.state_change signal — plugin/theme installs, updates, and activations. A php.fatal whose timestamp is minutes after a wp.state_change is almost always caused by that change.
5.2 Root Causes
(see root causes inline in 5.3 Fix)
5.3 Fix
Treat these in order; the first three account for the large majority of WordPress fatals.
Cause 1 — Plugin update broke an API contract
Signal pattern: wp.state_change (plugin update) followed within minutes by php.fatal with Call to undefined function or Class not found.
In logs: the file path in the fatal points inside wp-content/plugins/. The "undefined function" name often belongs to a different plugin entirely — typical when a helper plugin was deactivated or auto-disabled.
Fix:
- Disable the plugin from the file system:
mv wp-content/plugins/(or via WP-CLI:wp-content/plugins/ .off wp plugin deactivate). - Confirm the site loads.
- Roll the plugin back to the previous version (most managed hosts keep it; otherwise pull from the WordPress.org SVN tags).
- Re-enable.
Cause 2 — Memory exhaustion
Signal pattern: memory_near_limit warnings preceding a php.fatal with "Allowed memory size of X bytes exhausted".
In logs: the fatal names the file that was holding memory when the limit hit, but that is not always the actual leaker. Look for repetition — if the same file appears in dozens of php.fatal entries, that is your suspect.
Fix:
- Raise
WP_MEMORY_LIMITinwp-config.phpto256Mshort-term to restore the site. - Identify the memory hog with Query Monitor or
wp profile(WP-CLI). - Long-term, fix the actual cause — usually unbounded queries, image processing without limits, or a poorly-written REST endpoint.
Cause 3 — PHP version mismatch
Signal pattern: php.fatal with TypeError, ArgumentCountError, or "must be of type" messages, appearing right after a host-driven PHP upgrade.
In logs: the message names a function signature mismatch in plugin code that has not been updated for PHP 8.x.
Fix: roll PHP back to the last working minor (most hosts allow this), update the failing plugin to a current version, then move PHP forward again.
Cause 4 — Corrupted or partial plugin file
Signal pattern: php.fatal with syntax error, unexpected end of file or unexpected token.
In logs: the path identifies the file. This typically means an upload was interrupted or a deploy failed mid-write.
Fix: reinstall the plugin (wp plugin install ).
Cause 5 — Database connection or query error escalating to fatal
Signal pattern: php.fatal mentioning wpdb, mysqli, or "Error establishing a database connection" elevated to fatal.
Fix: verify DB credentials in wp-config.php, confirm the DB host is reachable, check for max-connections exhaustion on the DB side.
5.4 Verify
The signal that should disappear is php.fatal. That is the only honest measure of "fixed."
Concrete check:
# Watch for new fatals in real time
tail -f /var/log/php-fpm/www-error.log | grep --line-buffered "PHP Fatal error"
Healthy state:
- No new
PHP Fatal errorlines for at least 30 minutes under normal traffic (longer if the failing path was a low-traffic admin page — in that case actively visit the formerly broken URL). - The web server access log shows
http.requestresponses returning 2xx/3xx for the URLs that previously returned 5xx. - If memory was the cause, no further
Allowed memory sizeentries appear.
# Confirm 5xx rate has dropped to zero on the affected path
grep " /checkout " /var/log/nginx/access.log | awk '{print $9}' | sort | uniq -c
If php.fatal stays absent and 5xx on the affected URL drops to zero, the fix held. If a php.fatal reappears with a different file path, you are looking at a second, independent failure — repeat the diagnosis.
6. How to Catch This Early
Fixing it is straightforward once you know the cause. The hard part is knowing it happened at all.
This issue surfaces as php.fatal.
The hard truth about WordPress fatals: the fix is rarely the difficult part. The difficult part is knowing it happened and which file to look at, before a customer tells you.
By default, WordPress fatals are silent failures:
- The admin UI cannot warn you about the thing that broke it.
- The recovery email frequently does not arrive.
- Uptime checks see a 5xx but not the cause.
- The PHP error log is on a server you have to SSH into and grep.
This is the entire shape of the problem the php.fatal signal solves. Logystera's WordPress plugin reads PHP fatals as they happen, ships them as php.fatal signals with the message, file, line, and correlated wp.state_change events, and alerts on them — including the first one, not the hundredth. The same pipeline correlates http.request 5xx responses to the fatals that caused them, so you see "checkout broke at 14:02 because plugin X fataled in loader.php:142" instead of "500 error count: 47."
A site you can grep is one outage away from being a site you cannot grep. Treat fatals as a stream, not as files to discover after the fact.
7. Related Silent Failures
If you found this guide useful, the same pattern of silent, log-only failure shows up in:
- WordPress white screen of death after plugin update — same
php.fatalsignal, narrower trigger (recentwp.state_change). - WordPress 500 error after plugin update —
http.request5xx surface of the samephp.fatal. - WordPress memory limit exhausted —
memory_near_limitwarnings escalating tophp.fatal. - WordPress scheduled posts not publishing —
wp.cron type=missed_scheduleinstead of a fatal, but identical "no dashboard, no email, only logs" detection profile. - WordPress plugin silently deactivated after fatal —
wp.state_changetriggered by WordPress's own auto-disable safety net, often the only breadcrumb left after a fatal that has since "self-resolved."
See what's actually happening in your WordPress system
Connect your site. Logystera starts monitoring within minutes.