Fix WordPress “There has been a critical error”: enable WP_DEBUG and recover the site

Was this helpful?

If your WordPress site just face-planted into “There has been a critical error on this website,” you’re not alone. The message is intentionally vague, which is great for user experience and terrible for the person on-call. That person is you.

The good news: most “critical errors” are simple—one bad plugin update, a theme function calling something that no longer exists, or PHP running out of memory. The trick is moving from “something broke” to a specific stack trace, fast, without turning your production server into a public debug diary.

What WordPress “critical error” actually means

That banner is WordPress being polite about a PHP fatal error. Something threw an exception or hit a fatal condition and PHP stopped executing. WordPress couldn’t render the page, so it rendered the “critical error” fallback. In older eras you’d see the “white screen of death” (WSOD). Today you get a friendlier message and, sometimes, an email to the site admin with a recovery link.

On a functioning system, a fatal error should still leave a trail: PHP-FPM logs, Apache/Nginx error logs, a WordPress debug log (if enabled), and sometimes an application performance monitor trace. Your job is to collect the first useful stack trace and then make a clean decision: rollback, disable, patch, or restore.

What it is not

  • Not a database login failure. That usually shows “Error establishing a database connection.”
  • Not necessarily a server outage. Your web server can be healthy while PHP is crashing.
  • Not proof WordPress is “unstable.” It’s proof someone shipped code that didn’t match reality (versions, dependencies, assumptions).

Fast diagnosis playbook (first/second/third)

When a production site is down, you don’t “start exploring.” You run a short playbook and force the system to tell you what happened.

First: confirm it’s a PHP fatal and get the exact error line

  • Check the web server error log and PHP-FPM log for the last few minutes.
  • If you see a stack trace mentioning a plugin or theme path, you already have a target.
  • If logs are empty or useless, enable WordPress debug logging to file only and reload once.

Second: isolate the change that triggered it

  • Ask: what changed? Plugin auto-update, theme update, PHP upgrade, new MU plugin, security hardening?
  • Roll back the most recent change first. Don’t do five “fixes” and then wonder which one worked.

Third: restore service with the least risky workaround

  • Disable the offending plugin (rename directory or use WP-CLI) and bring the site up.
  • Switch to a default theme if the theme is at fault.
  • If core files are corrupted, reinstall core (without touching wp-content).
  • If nothing else: restore from a known-good backup, then re-apply changes carefully.

Yes, you can spend an hour debugging the underlying bug. But if the CEO is watching the homepage load test on their phone, you first make it load.

A few useful facts and history (so you stop guessing)

  1. WordPress introduced “fatal error recovery mode” in 5.2 (2019), including admin emails and a “recovery” login link when a plugin/theme fatals.
  2. The classic WSOD was often “just” PHP fatal output suppressed by display_errors=Off and no log configuration—silence, not absence.
  3. WP_DEBUG is a WordPress constant, not a PHP setting. It changes WP behavior (notably notices) but doesn’t replace PHP error logging.
  4. WP_DEBUG_LOG can log to wp-content/debug.log even when errors aren’t displayed to users—useful, and also a privacy hazard if misconfigured.
  5. Many critical errors are version skew. Plugin requires PHP 8.1; server is PHP 7.4. Or plugin expects WordPress hooks that arrived in newer core.
  6. Opcode caching (OPcache) can make rollbacks look “ignored.” You deploy a fix, but the old bytecode sticks until cache resets.
  7. Auto-updates reduced patch lag but increased surprise outages. Especially on sites with “works on my staging” plugins and no integration tests.
  8. Some hosts intercept PHP errors and show their own friendly page, which can hide the real failure unless you inspect server-side logs.

One more operational truth: WordPress is a PHP app that runs in a shared ecosystem of web server + PHP handler + filesystem + database + cache. Most outages are edges between those parts, not “WordPress itself.”

Safety rules before you touch WP_DEBUG

Debugging is where good intentions turn into data leaks. Be deliberate.

  • Never enable public error display on production. That means: keep WP_DEBUG_DISPLAY off, keep PHP display_errors off.
  • Log to file, not to the browser. Browser output can expose secrets, paths, and tokens to everyone, including crawlers.
  • Assume debug logs contain personal data. Emails, cookies, sometimes request headers—depending on what plugins dump.
  • Timebox it. Enable logging, reproduce once, capture the stack trace, then disable or rotate logs.
  • Don’t “chmod 777” your way out. You will fix the error and create a bigger one.

Joke #1: Enabling WP_DEBUG_DISPLAY on production is like announcing your passwords over a stadium microphone—technically efficient, socially catastrophic.

Enable WP_DEBUG properly (and capture the real error)

You enable three things in wp-config.php: debug mode, log-to-file, and no display. Optional: set a custom error log path outside the web root (better). Also consider disabling concatenated scripts, which can help when debugging admin JS issues, but that’s usually not the “critical error” case.

Recommended production-safe debug settings

Place these above the line that says /* That's all, stop editing! */. If you don’t see that line, your wp-config.php might be customized; still place them before WordPress loads.

cr0x@server:~$ sudo sed -n '1,180p' /var/www/html/wp-config.php
...output...

What you want added (shown here as a patch-style mental model, not a literal command) is:

  • define('WP_DEBUG', true);
  • define('WP_DEBUG_LOG', true); or a path like /var/log/wordpress/debug.log
  • define('WP_DEBUG_DISPLAY', false);
  • @ini_set('display_errors', 0); (defense-in-depth; PHP config should already do it)

Opinion: if you can, log to /var/log/wordpress/ with permissions locked down, not to wp-content/debug.log. Too many setups accidentally serve files from wp-content if someone misconfigures Nginx locations or adds a permissive rule.

After you capture the error, turn it back off

Debug mode is not a lifestyle. It’s a diagnostic tool. If you leave it on, you’ll bloat logs, leak paths, and degrade performance with excessive notices.

Hands-on tasks: commands, outputs, and decisions (12+)

Below are real tasks you can run over SSH. Each includes: the command, what the output means, and what decision you make. Adjust paths for your distro and vhost layout. When in doubt, search your configs rather than trusting memory.

Task 1: Verify the site is actually failing the way users see it

cr0x@server:~$ curl -I https://example.com/
HTTP/2 500
date: Thu, 26 Dec 2025 12:11:09 GMT
content-type: text/html; charset=UTF-8

Meaning: HTTP 500 confirms server-side failure (not just a browser cache issue).

Decision: Move to server logs immediately; don’t waste time in wp-admin links that won’t load.

Task 2: Check Nginx error log around the incident window

cr0x@server:~$ sudo tail -n 80 /var/log/nginx/error.log
2025/12/26 12:10:58 [error] 2211#2211: *184 FastCGI sent in stderr: "PHP message: PHP Fatal error:  Uncaught Error: Call to undefined function wp_get_environment_type() in /var/www/html/wp-content/plugins/acme-cache/acme-cache.php:91
Stack trace:
#0 /var/www/html/wp-settings.php(526): include_once()
#1 /var/www/html/wp-config.php(102): require_once('...')
#2 /var/www/html/wp-load.php(50): require_once('...')
#3 /var/www/html/wp-blog-header.php(13): require_once('...')
#4 /var/www/html/index.php(17): require('...')
#5 {main}
  thrown in /var/www/html/wp-content/plugins/acme-cache/acme-cache.php on line 91" while reading response header from upstream, client: 203.0.113.44, server: example.com, request: "GET / HTTP/2.0", upstream: "fastcgi://unix:/run/php/php8.1-fpm.sock:", host: "example.com"

Meaning: You have the smoking gun: plugin acme-cache calls a WordPress function not available in this core version.

Decision: Disable that plugin first to restore service, then address version compatibility.

Task 3: Check PHP-FPM pool log (if Nginx doesn’t show enough)

cr0x@server:~$ sudo tail -n 60 /var/log/php8.1-fpm.log
[26-Dec-2025 12:10:58] WARNING: [pool www] child 3112 said into stderr: "PHP Fatal error:  Uncaught Error: Call to undefined function wp_get_environment_type() in /var/www/html/wp-content/plugins/acme-cache/acme-cache.php:91"

Meaning: Confirms it’s not an Nginx parsing fluke; it’s PHP dying.

Decision: Proceed with plugin disable; no need to enable WP_DEBUG yet if logs already show the trace.

Task 4: Enable WP debug logging (file only) for cases where logs are silent

cr0x@server:~$ sudo grep -n "WP_DEBUG" -n /var/www/html/wp-config.php

Meaning: Empty output means debug constants aren’t set.

Decision: Add production-safe debug settings. If output shows conflicting definitions, fix duplicates (first definition wins in surprising ways).

Task 5: Create a safer log directory outside web root

cr0x@server:~$ sudo install -d -o www-data -g www-data -m 0750 /var/log/wordpress

Meaning: Directory exists, owned by the web user, readable only by owner/group.

Decision: Use /var/log/wordpress/debug.log as WP_DEBUG_LOG target.

Task 6: Edit wp-config.php safely and verify syntax

cr0x@server:~$ sudo php -l /var/www/html/wp-config.php
No syntax errors detected in /var/www/html/wp-config.php

Meaning: Your edit didn’t introduce a parse error. Yes, people do this at 2 a.m.

Decision: If you see “Parse error,” revert immediately; a parse error will brick everything, including WP recovery mode.

Task 7: Trigger one request and inspect the WordPress debug log

cr0x@server:~$ curl -sS -o /dev/null -w "%{http_code}\n" https://example.com/
500
cr0x@server:~$ sudo tail -n 80 /var/log/wordpress/debug.log
[26-Dec-2025 12:12:11 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function wp_get_environment_type() in /var/www/html/wp-content/plugins/acme-cache/acme-cache.php:91

Meaning: Debug log confirms the failing file/line.

Decision: Disable that plugin; don’t keep refreshing and generating noise.

Task 8: Disable a plugin without wp-admin by renaming its directory

cr0x@server:~$ cd /var/www/html/wp-content/plugins
cr0x@server:~$ sudo mv acme-cache acme-cache.disabled

Meaning: WordPress can’t load the plugin; it will mark it inactive.

Decision: Reload site. If it returns 200, you’ve restored service; then investigate compatibility and update strategy.

Task 9: Use WP-CLI to list plugins and deactivate cleanly (preferred when possible)

cr0x@server:~$ cd /var/www/html
cr0x@server:~$ sudo -u www-data wp plugin list --status=active
+-------------------+----------+--------+---------+
| name              | status   | update | version |
+-------------------+----------+--------+---------+
| woocommerce       | active   | none   | 8.2.1   |
| acme-cache        | active   | none   | 3.4.0   |
+-------------------+----------+--------+---------+
cr0x@server:~$ sudo -u www-data wp plugin deactivate acme-cache
Plugin 'acme-cache' deactivated.

Meaning: WP-CLI can talk to your WordPress install; that’s a strong sign DB is reachable and core loads at least partly.

Decision: Prefer WP-CLI deactivation over directory renames for cleaner state—unless the fatal prevents WP-CLI from booting.

Task 10: Check current WordPress core version and compare to plugin requirements

cr0x@server:~$ sudo -u www-data wp core version
5.6.14

Meaning: Core is old. Many modern plugins assume newer functions exist.

Decision: Plan a controlled core update in staging, not a panicked production upgrade—unless security forces your hand.

Task 11: Switch theme to a default one to rule out theme fatals

cr0x@server:~$ sudo -u www-data wp theme list
+------------------+----------+--------+---------+
| name             | status   | update | version |
+------------------+----------+--------+---------+
| twentytwentyfour | inactive | none   | 1.2     |
| custom-corp      | active   | none   | 9.7     |
+------------------+----------+--------+---------+
cr0x@server:~$ sudo -u www-data wp theme activate twentytwentyfour
Success: Switched to 'Twenty Twenty-Four' theme.

Meaning: If the site comes back, the theme is the culprit (often functions.php or a custom include).

Decision: Keep default theme temporarily to restore service, then fix theme code in a controlled deploy.

Task 12: Confirm PHP version and modules (common compatibility landmine)

cr0x@server:~$ php -v
PHP 8.1.2 (cli) (built: Jan 15 2025 10:22:01) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.2, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.2, Copyright (c), by Zend Technologies

Meaning: CLI PHP version is 8.1. That’s not always the same as the FPM version, but it’s a hint.

Decision: Also check which PHP-FPM socket you’re using in Nginx/Apache. Version skew between CLI and FPM leads to absurd debugging sessions.

Task 13: Identify the PHP-FPM backend used by the site

cr0x@server:~$ sudo grep -R "fastcgi_pass" -n /etc/nginx/sites-enabled | head
/etc/nginx/sites-enabled/example.conf:42: fastcgi_pass unix:/run/php/php8.1-fpm.sock;

Meaning: Nginx is explicitly using php8.1-fpm.

Decision: If the socket points to an older/newer PHP than expected, align it. Lots of “critical errors” are just “wrong PHP.”

Task 14: Check memory limit issues (fatal errors that look random)

cr0x@server:~$ sudo -u www-data wp eval 'echo ini_get("memory_limit"), PHP_EOL;'
128M

Meaning: Memory limit is 128M. For modern WooCommerce + page builders, that can be tight.

Decision: If logs show “Allowed memory size exhausted,” raise memory limit in PHP-FPM pool or php.ini and re-test. Don’t blindly set it to 2G; fix the hog too.

Task 15: Check disk space and inode exhaustion (yes, this breaks WordPress)

cr0x@server:~$ df -h /var/www /var/log
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        40G   38G  1.2G  97% /
cr0x@server:~$ df -i /var/www
Filesystem      Inodes  IUsed   IFree IUse% Mounted on
/dev/vda1      2621440 2620000   1440  100% /

Meaning: Inodes are effectively exhausted. PHP can fail writing sessions, caches, uploads, logs. Errors cascade.

Decision: Clean up small-file explosions (cache directories, old backups, debug logs), then consider moving uploads/cache to separate storage.

Task 16: Check database connectivity from WP-CLI

cr0x@server:~$ sudo -u www-data wp db check
Success: Database checked.

Meaning: DB is reachable and tables are OK at a basic level.

Decision: If this fails, stop blaming plugins; fix DB credentials, MySQL availability, or permissions first.

Task 17: Clear OPcache (when you’re sure your deploy is correct but behavior isn’t)

cr0x@server:~$ sudo systemctl reload php8.1-fpm

Meaning: Reload typically flushes OPcache and restarts workers gracefully (depends on config).

Decision: Use reload after code changes when symptoms don’t match the filesystem. If you need a hard reset, restart—but be mindful of concurrency and traffic.

Recovery paths: plugins, themes, core, PHP

Path A: A plugin update broke the site

This is the most common. The failure mode is: plugin assumes a function/class exists, or it introduced a syntax error, or it now requires a newer PHP version.

Do this:

  • Disable the plugin (WP-CLI deactivate, or rename directory).
  • Bring the site back up.
  • Then decide: upgrade core/PHP to meet requirements, or roll back plugin to a compatible version.

Avoid this: leaving the plugin disabled without understanding what it did. If it handled caching, security, payments, or forms, you may have restored the homepage but silently broken revenue.

Path B: The theme is fataling (functions.php is a crime scene)

Themes often embed “mini framework” code. Custom themes especially like to call functions from plugins they assume are active. Then someone disables the plugin, and the theme falls over.

  • Switch to a default theme via WP-CLI.
  • If WP-CLI can’t load, rename wp-content/themes/custom-theme and WordPress will fall back.
  • Once stable, fix the theme to gracefully handle missing dependencies.

Path C: Core mismatch or corruption

Sometimes “critical error” happens because core files are missing (bad deploy) or modified (compromise, or a plugin scribbled over something it shouldn’t).

Fix: reinstall WordPress core without touching wp-content and wp-config.php.

cr0x@server:~$ cd /var/www/html
cr0x@server:~$ sudo -u www-data wp core verify-checksums
Warning: File should not exist: wp-includes/some-stray-file.php
Error: Checksum verification failed.

Decision: If checksums fail, reinstall core (wp core download --force) and then re-verify. If unexpected files exist, treat it as a security incident until proven otherwise.

Path D: PHP version upgrade broke a plugin (or fixed it and exposed old bugs)

PHP upgrades are great until they aren’t. Deprecated features become fatal, strict typing tightens, and libraries behave differently.

Strategy:

  • Confirm which PHP version is used by the web handler (FPM) and compare to what your WordPress and plugins support.
  • If you must downgrade temporarily, do it cleanly (switch FPM socket, reload web server), not by editing random symlinks.
  • Long term: update plugins/themes to be compatible; don’t freeze PHP forever. That ends with you running an internet-facing museum exhibit.

Path E: Resource exhaustion (memory, disk, CPU) triggers cascading failures

WordPress “critical error” can be the visible symptom of a server that’s already dying. When the box is low on disk or memory, writing session files fails, cache directories can’t update, and PHP workers crash.

Fix the platform first: free space, rotate logs, correct memory limits, add swap if you must (as a short-term crutch), and reduce PHP-FPM worker count if it’s thrashing the machine.

Joke #2: The only thing that grows faster than WordPress plugins is the debug log you forgot to rotate.

Three corporate mini-stories from the trenches

Mini-story 1: The outage caused by a wrong assumption

A mid-sized retail company ran WordPress for marketing pages and a separate platform for checkout. Someone added a performance plugin that “required WordPress 5.8+” but the site had been pinned at 5.6 for compatibility with a legacy page builder. Nobody noticed the requirement line because the plugin installed fine and the staging environment was newer than production.

On a Monday morning, auto-updates kicked in and pulled a major plugin version. The plugin started calling a core function introduced after 5.6. The result was an immediate fatal error on every request. The uptime monitor screamed, the marketing team screamed louder, and the infrastructure team got blamed for “server issues” because the site returned HTTP 500.

The fix was simple: disable the plugin via directory rename, restore service, and then align environments. The real lesson was uglier: staging had quietly drifted. Everyone assumed “staging equals production,” because saying that feels professional. It wasn’t true.

After the incident, they put one boring gate in place: a nightly job that compares WordPress core version, PHP-FPM version, and active plugin versions between staging and production. The next time a plugin required a newer core, they saw the mismatch before users did.

Mini-story 2: The optimization that backfired

A large internal communications site was slow in the admin area. An engineer enabled aggressive object caching and moved sessions to the filesystem for “simplicity.” They also tuned PHP-FPM to run more workers, because the CPU graph looked “not too high.” It was the classic move: optimize the metric you can see and ignore the one you didn’t measure.

Within days, the server started showing intermittent critical errors. Not constant—worse. Users would refresh and sometimes it worked. Logs showed a mix: “Allowed memory size exhausted,” “failed to open stream,” and occasional database timeouts. The immediate reaction was to blame WordPress, then to blame MySQL, then to blame the network, because those are emotionally satisfying targets.

The root cause: inode exhaustion and disk contention from a cache implementation that wrote thousands of tiny files combined with too many PHP-FPM workers thrashing the disk. When the filesystem couldn’t create new cache/session files, PHP calls failed in unexpected places, and plugins handled failures poorly, leading to fatals.

They rolled back file-based caching, moved to a proper in-memory cache service, and reduced PHP-FPM workers to match IO capacity. Performance improved and the “random” critical errors vanished. The moral: the bottleneck you ignore will choose its own moment to educate you.

Mini-story 3: The boring but correct practice that saved the day

A financial services team ran WordPress in a tightly controlled environment: no auto-updates in production, changes deployed through CI, and a weekly maintenance window. It wasn’t sexy, but it was predictable. They also kept a tested restore procedure: not “we have backups,” but “we restored yesterday and it worked.”

One evening, a content editor installed a plugin on staging to preview a feature. Fine. Except the plugin vendor’s uninstall routine was buggy and left behind a must-use plugin file in wp-content/mu-plugins. That file made it into a release artifact and was deployed to production during the maintenance window.

The site immediately hit a critical error due to a missing dependency the MU plugin assumed existed. The on-call engineer followed the runbook: confirm fatal in logs, disable MU plugin by moving the file, reload PHP-FPM, verify 200s. Service was restored quickly.

Then the boring practice mattered: they rolled forward a corrected release and used their diff tooling to prove exactly what changed. No mystery. No “maybe it was the database.” The incident report was short, factual, and useful—which is the best kind.

Common mistakes: symptom → root cause → fix

This section exists because people keep repeating the same errors, and I enjoy not doing the same incident twice.

1) Symptom: “Critical error” only on certain pages

Root cause: A plugin triggers a fatal only when a specific shortcode, template, or WooCommerce route loads.

Fix: Hit the failing URL while tailing logs. Disable the plugin/theme component that hooks that route. If it’s content-based (shortcode), edit the post in the database or via WP-CLI to remove the shortcode temporarily.

2) Symptom: Site down, wp-admin also down, WP-CLI fails with a fatal

Root cause: A must-use plugin or a file loaded very early fatals before WP can bootstrap.

Fix: Check wp-content/mu-plugins. Move files out one by one. Also check advanced-cache.php and object-cache.php in wp-content (drop-in plugins).

3) Symptom: You enabled WP_DEBUG and now visitors see raw errors

Root cause: WP_DEBUG_DISPLAY or PHP display_errors is on.

Fix: Set define('WP_DEBUG_DISPLAY', false); and ensure PHP config has display_errors=Off. Reload PHP-FPM. Confirm with a test request; errors should go to the log only.

4) Symptom: You “fixed” the plugin but the error persists

Root cause: OPcache serving old bytecode, or you edited the wrong server (multi-node, wrong container, wrong volume).

Fix: Reload/restart PHP-FPM, confirm the file content on the host serving traffic, and verify upstream load balancer targets. Don’t trust your SSH prompt; verify.

5) Symptom: Critical error after migrating hosts

Root cause: Missing PHP extensions (mbstring, intl), wrong file permissions/ownership, or incompatible PHP version.

Fix: Compare module list and PHP version; correct ownership to the web user; ensure WordPress can read/write where needed (wp-content/uploads, cache dirs).

6) Symptom: “Allowed memory size exhausted” in logs

Root cause: Low PHP memory limit, runaway plugin, or huge autoloaded options in the database.

Fix: Raise memory to a sane level (256M is often reasonable), then profile. Use WP-CLI to inspect autoloaded options and trim offenders.

7) Symptom: debug.log grows rapidly and fills disk

Root cause: WP_DEBUG left on; plugin emits repeated notices/warnings; no log rotation.

Fix: Disable WP_DEBUG after capture. Add logrotate for the log path. Fix the underlying spammy plugin/theme code.

8) Symptom: Critical error appears, then disappears, then returns

Root cause: One node in a cluster has a different plugin set, different filesystem, or different PHP version.

Fix: Compare nodes: plugin directories, checksums, PHP-FPM versions, mounted volumes. Make deployments immutable and consistent.

Checklists / step-by-step plan

Immediate restore checklist (aim: under 15 minutes)

  1. Confirm status code and scope: one URL, all URLs, admin too.
  2. Tail Nginx/Apache error log and PHP-FPM log for the exact fatal message.
  3. If logs are silent: enable WP_DEBUG with WP_DEBUG_LOG and WP_DEBUG_DISPLAY=false.
  4. Identify whether the fatal references a plugin or theme path.
  5. Disable the suspected plugin/theme (WP-CLI preferred; rename directory/file if necessary).
  6. Reload PHP-FPM to clear OPcache if behavior doesn’t match filesystem.
  7. Re-test: curl for 200, then load homepage in a browser, then check a few key routes (login, checkout, contact form).
  8. Capture the stack trace and write down the change that triggered the incident.
  9. Turn off WP_DEBUG (or at least stop verbose logging) after you have the evidence.

Root-cause and prevent-repeat checklist (aim: same day)

  1. Compare versions: WordPress core, PHP-FPM, active plugins, theme.
  2. Review recent changes: auto-updates, deploys, config changes, host migrations.
  3. Reproduce in staging with matching versions.
  4. Decide on strategy: upgrade core/PHP, pin plugin versions, or replace plugin.
  5. Add a guardrail: disable auto-updates for risky plugins, or only allow updates via CI.
  6. Implement log rotation for WordPress debug logs and web/PHP logs.
  7. Add a smoke test: fetch homepage + a few key routes after deploy.

Minimal safe WP_DEBUG configuration checklist

  • WP_DEBUG true only while diagnosing.
  • WP_DEBUG_LOG to a protected path.
  • WP_DEBUG_DISPLAY false.
  • PHP display_errors off.
  • Access controls so log files aren’t web-accessible.

One operations quote worth keeping in your pocket

Paraphrased idea (attributed to W. Edwards Deming): Without data, you’re just another person with an opinion.

WP_DEBUG, when used correctly, is how you turn an outage from “opinions” into “here’s the exact line that broke.”

FAQ

1) Why does WordPress show “There has been a critical error” instead of the real error?

Because showing raw PHP errors to users is a security and privacy risk. WordPress hides the details and expects you to consult server-side logs or enable safe debug logging.

2) Will enabling WP_DEBUG slow down my site?

It can. It increases logging and surfaces notices that some plugins trigger constantly. Use it briefly, log to file, then disable. For longer-term observability, use structured logging and proper monitoring instead.

3) Is wp-content/debug.log safe?

Sometimes. It depends on your web server rules. If your server can serve files from wp-content directly (common), you risk exposing the log. A protected path like /var/log/wordpress is safer.

4) I can’t access wp-admin. How do I disable plugins?

Use WP-CLI if it boots. Otherwise rename the plugin directory under wp-content/plugins or move the plugin file out of mu-plugins. WordPress will skip what it can’t find.

5) What if disabling all plugins doesn’t fix it?

Then look at the theme, MU plugins, and drop-ins (object-cache.php, advanced-cache.php). If none of those, verify core checksums and check PHP version/modules and filesystem health (disk/inodes).

6) How do I tell if it’s a PHP memory issue?

Your logs will say “Allowed memory size exhausted.” Don’t guess. Confirm memory limit via WP-CLI or phpinfo (in a safe way), raise it moderately, then hunt the plugin/theme causing the spike.

7) Why does the error only happen sometimes?

Intermittent failures usually mean one node in a cluster differs, or resource exhaustion is periodic (cron jobs, backups, cache rebuilds), or OPcache is serving stale code on some workers.

8) Should I restore from backup immediately?

If you can’t identify the failing component quickly and the business impact is high, yes—restore is a valid incident response. But capture logs first, otherwise you’ll repeat the outage next update.

9) Can I “fix” this by reinstalling WordPress?

You can reinstall core safely, but it rarely fixes plugin/theme compatibility bugs. Reinstalling everything is often a dramatic way to avoid reading the stack trace.

10) How do I prevent this class of outage?

Stop letting production be your integration environment: pin versions, test updates in staging that matches production, deploy through CI, and keep a rollback/restore procedure you’ve actually exercised.

Conclusion: next steps that prevent repeat incidents

“There has been a critical error” is WordPress telling you: “PHP died, please go read the receipts.” Your fastest path is consistent: check server logs, enable WP_DEBUG logging safely if needed, isolate the offending plugin/theme, restore service, then fix the version mismatch or bug in a controlled way.

Do these next:

  • Turn off WP_DEBUG if you enabled it, or at least stop verbose logging once you have the stack trace.
  • Write down the trigger: which update, which deploy, which configuration change.
  • Make staging match production (versions, PHP handler, plugins). Drift is how you end up debugging fiction.
  • Add one automated smoke test after updates: homepage + login + a key business route. Cheap, effective.
  • Rotate logs and watch disk/inodes. Outages caused by full disks are not “mysterious,” just embarrassing.

If you do nothing else, do this: treat WordPress updates like software releases, not like background noise. Production has enough surprises already.

← Previous
How x86 Was Born: Why the 8086 Became an “Accidental” Standard for Decades
Next →
Ubuntu 24.04: Fail2ban isn’t banning anything — the quick verification workflow

Leave a comment