Your site was fine. Then you updated “one small plugin.” Now you’re staring at a 500 error, a white screen, or a wp-admin that politely refuses to load. The business wants an ETA. Your pager is making that sound again. Welcome.
This is a recovery guide for people who need the site back now, without making the post-mortem worse. We’ll disable the broken plugin from the filesystem (FTP/SSH), confirm what actually happened, and put guardrails in place so the next update doesn’t turn into an incident.
Fast diagnosis playbook (first 10 minutes)
You’re trying to answer one question: Is the site down because PHP is crashing, because the database is unreachable, or because WordPress is stuck in a bad state (maintenance mode, autoloaded options, plugin conflict)?
Don’t “try random fixes.” That’s how you end up with a working site and no idea why, which is a polite way of saying “repeat incident.” Here’s the order that finds the bottleneck quickly.
1) Confirm the failure mode from the outside
- If you see HTTP 500/502/503: suspect PHP fatal errors, upstream timeouts, or maintenance mode.
- If you see a white screen (no HTML): classic PHP fatal or exhausted memory.
- If wp-admin loads but actions fail: database writes, permissions, nonce/session issues, or a specific plugin hook.
- If only the homepage fails: theme, caching layer, page builder plugin, or a specific route.
2) Check server logs before touching WordPress
Logs tell you whether you’re dealing with a plugin fatal error, a permission problem, or something lower-level (PHP-FPM down, disk full). If you can’t find logs quickly, you can still proceed to disable plugins via filesystem as a blunt instrument—but it’s better when you can name the offender.
3) Disable the suspected plugin (single plugin first)
If you know which plugin was updated, disable that one by renaming its folder. If you don’t know, disable all plugins by renaming the plugins directory. Get the site back, then narrow down.
4) Clear caches and confirm PHP is healthy
Object cache, page cache, CDN cache, and PHP opcache can all happily serve broken behavior after you “fixed” the files. Confirm with a direct request, check logs again, and only then declare victory.
5) Stabilize before re-enabling anything
Once the site is back, your job changes: preserve evidence (logs), prevent auto-updates from re-breaking things, and create a safe path to reintroduce the plugin or roll it back.
One quote worth keeping on your desk: Paraphrased idea — Gene Kranz: failure isn’t acceptable; teams succeed by disciplined preparation and execution under pressure.
What usually breaks when a plugin “breaks WordPress”
WordPress plugins are not “extensions” in the gentle sense. They’re chunks of PHP that run inside your request lifecycle with the same privileges as core. A plugin can:
- Throw a fatal error (syntax error, missing class/function, PHP version mismatch).
- Blow up memory or timeouts (infinite loops, huge autoloaded options, expensive queries).
- Break admin sessions (cookies, nonces, redirects).
- Corrupt rewrite rules or output invalid headers.
- Trigger database schema changes that partially apply.
Two major “gotchas” that make plugin incidents feel random:
- Autoloaded options: Some plugins store large data in
wp_optionswithautoload = 'yes'. That means WordPress drags it into memory on many requests. Everything slows down, then dies. - Load order and hooks: Your site might only break for logged-in users, or only on cron, because that’s where the plugin hook runs.
Joke #1: A plugin update is like “just a quick change” on Friday—technically possible, spiritually unwise.
Recovery path A: disable the plugin via FTP / file manager
If you have FTP or a hosting file manager but no shell, you can still recover quickly. The goal is to make WordPress stop loading the plugin code. WordPress loads plugins by scanning directories under wp-content/plugins. If the directory name changes, WordPress considers it missing and deactivates it.
Disable one plugin (preferred)
- Connect via FTP / open the hosting file manager.
- Navigate to:
public_html/wp-content/plugins/(your root may differ). - Find the plugin folder that was updated or is suspicious.
- Rename it, for example:
elementor→elementor.disabledwoocommerce→woocommerce.off
- Reload the site and wp-admin.
What this does: WordPress sees the plugin is missing and marks it deactivated. It’s crude, but it works even when PHP is on fire.
Disable all plugins (nuclear, but fast)
- Go to
wp-content/. - Rename
plugins→plugins.disabled. - Reload. If the site is back, you’ve proven the incident is plugin-related.
- Create a new empty
pluginsdirectory (WordPress expects it), then move plugins back one by one.
When FTP recovery fails
FTP is fine until permissions, ownership, or caching get weird. If renaming doesn’t stick, or changes revert, you’re probably dealing with:
- a deployment system overwriting files
- read-only filesystem / permission issues
- multiple WordPress copies and you’re editing the wrong one
At that point you need SSH or your hosting provider’s support to confirm the actual document root and ownership.
Recovery path B: disable the plugin via SSH (and why it’s better)
SSH turns recovery from “click-and-pray” into “observe, change, verify.” You can tail logs, confirm paths, and revert cleanly.
The minimum viable SSH plan
- Find the WordPress root directory.
- Confirm the plugin directory and the plugin folder name.
- Rename the plugin folder (or
pluginsdirectory) to disable. - Check logs to confirm the fatal error stops.
- Reload with
curland verify HTTP status and content.
Why renaming works reliably
WordPress stores “active plugins” in the database, but it still checks whether the plugin file exists. If the folder is gone, WordPress can’t include it, and it deactivates it on the next load. Renaming is effectively an “air gap” between WordPress and broken PHP.
Recovery path C: WP-CLI deactivate (the cleanest option)
If WP-CLI is installed and you can run it as the correct user, this is the most controlled option. It updates WordPress’s internal state instead of relying on filesystem tricks. But if PHP is fatally broken before WP-CLI can bootstrap, renaming still wins.
Verify recovery like an SRE (don’t trust the homepage)
Bringing back the homepage is nice. It’s not “recovered.” Real verification checks:
- wp-admin loads and login works
- a cache-bypassed request returns 200
- error logs stop showing fatals
- checkout/contact forms still submit
- cron isn’t spamming errors
Also: take a snapshot (backup) after stabilizing. Not before. A backup of a broken state is a souvenir, not a solution.
Practical tasks with commands: what output means and what you do next
Below are hands-on tasks you can run over SSH. Each one includes (1) the command, (2) example output, (3) what the output means, and (4) the decision you make next.
Task 1: Confirm you’re in the right WordPress root
cr0x@server:~$ cd /var/www/example.com/public_html && ls -la
total 248
drwxr-xr-x 7 www-data www-data 4096 Dec 27 09:10 .
drwxr-xr-x 3 root root 4096 Dec 20 11:02 ..
-rw-r--r-- 1 www-data www-data 420 Nov 3 10:21 index.php
-rw-r--r-- 1 www-data www-data 19935 Nov 3 10:21 wp-blog-header.php
-rw-r--r-- 1 www-data www-data 3516 Nov 3 10:21 wp-config.php
drwxr-xr-x 9 www-data www-data 4096 Dec 10 12:01 wp-content
drwxr-xr-x 8 www-data www-data 4096 Nov 3 10:21 wp-admin
drwxr-xr-x 25 www-data www-data 4096 Nov 3 10:21 wp-includes
Meaning: The presence of wp-config.php, wp-admin, and wp-includes strongly suggests you’re in the right place.
Decision: Proceed. If you don’t see these, stop and find the real document root. Disabling plugins in the wrong directory is how people “fix” nothing for an hour.
Task 2: Identify the last modified plugin directories (often the culprit)
cr0x@server:~$ cd /var/www/example.com/public_html/wp-content/plugins && ls -lt | head
total 64
drwxr-xr-x 12 www-data www-data 4096 Dec 27 09:02 some-plugin
drwxr-xr-x 10 www-data www-data 4096 Dec 27 08:58 cache-tool
drwxr-xr-x 8 www-data www-data 4096 Dec 10 12:00 seo-pack
drwxr-xr-x 15 www-data www-data 4096 Dec 1 15:22 woocommerce
Meaning: Plugins updated recently rise to the top. That timestamp often lines up with the outage.
Decision: Start by disabling the most recently modified plugin that matches the change window.
Task 3: Disable a single plugin by renaming its directory
cr0x@server:~$ mv /var/www/example.com/public_html/wp-content/plugins/some-plugin /var/www/example.com/public_html/wp-content/plugins/some-plugin.disabled
Meaning: No output is normal for mv. If it errors, you’ll see permission or missing path problems.
Decision: If the site comes back, you’ve isolated the offender. If not, move to disabling all plugins or checking logs for a different failure mode.
Task 4: Disable all plugins by renaming the plugins directory
cr0x@server:~$ cd /var/www/example.com/public_html/wp-content && mv plugins plugins.disabled && mkdir plugins
Meaning: WordPress will treat all plugins as missing; creating an empty plugins directory avoids warnings and keeps future installs sane.
Decision: If the site is back now, you know it’s plugin-related. If it’s still down, focus on PHP, database, or web server.
Task 5: Curl the site and confirm status without a browser’s cache
cr0x@server:~$ curl -sS -D- -o /dev/null https://example.com/ | head -n 12
HTTP/2 200
date: Sat, 27 Dec 2025 09:12:10 GMT
content-type: text/html; charset=UTF-8
cache-control: no-cache, must-revalidate, max-age=0
server: nginx
Meaning: HTTP 200 suggests the web tier and PHP are responding. Headers hint whether caching is in play.
Decision: If you still see 500/502/503, inspect logs immediately. If it’s 200 but content is wrong, suspect caching or partial failures.
Task 6: Tail PHP-FPM or web error logs to catch the fatal error line
cr0x@server:~$ sudo tail -n 60 /var/log/nginx/error.log
2025/12/27 09:03:44 [error] 22110#22110: *881 FastCGI sent in stderr: "PHP message: PHP Fatal error: Uncaught Error: Call to undefined function some_plugin_init() in /var/www/example.com/public_html/wp-content/plugins/some-plugin/some-plugin.php:42
Stack trace:
#0 /var/www/example.com/public_html/wp-settings.php(453): include_once()
#1 /var/www/example.com/public_html/wp-config.php(92): require_once('...')
#2 /var/www/example.com/public_html/wp-load.php(50): require_once('...')
#3 /var/www/example.com/public_html/wp-blog-header.php(13): require_once('...')
#4 /var/www/example.com/public_html/index.php(17): require('...')
#5 {main}
thrown" while reading response header from upstream, client: 203.0.113.10, server: example.com, request: "GET / HTTP/2.0"
Meaning: This is the smoking gun: undefined function in a plugin file. Often caused by a missing dependency, partial update, or PHP version mismatch.
Decision: Disable that plugin (folder rename) and keep it disabled until you can either roll back or fix the environment.
Task 7: Confirm disk space (full disks cause “random” PHP failures)
cr0x@server:~$ df -h /var/www
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 39G 420M 99% /
Meaning: 99% used is incident territory. Updates can fail mid-extract, logs can’t write, PHP sessions can’t save. Everything gets flaky.
Decision: Free space first. Otherwise you’ll “fix” the plugin and still crash five minutes later.
Task 8: Look for a stuck maintenance mode file
cr0x@server:~$ ls -la /var/www/example.com/public_html/.maintenance
-rw-r--r-- 1 www-data www-data 55 Dec 27 09:01 /var/www/example.com/public_html/.maintenance
Meaning: WordPress drops .maintenance during updates. If the update crashes, the file can linger and keep the site in maintenance mode.
Decision: Remove it if you’re not actively updating.
cr0x@server:~$ rm -f /var/www/example.com/public_html/.maintenance
Task 9: Validate PHP version vs plugin requirements
cr0x@server:~$ php -v
PHP 7.4.33 (cli) (built: Nov 8 2024 10:14:11) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
Meaning: Many modern plugins increasingly require PHP 8.x. If a plugin update assumed PHP 8 and you’re on 7.4, fatal errors can happen immediately.
Decision: If the plugin requires newer PHP, keep it disabled and plan an orderly PHP upgrade (or roll back plugin version). Don’t “quick upgrade PHP” mid-incident unless you enjoy long evenings.
Task 10: Check file ownership/permissions (failed updates often leave root-owned files)
cr0x@server:~$ find /var/www/example.com/public_html/wp-content/plugins -maxdepth 2 -type f -name '*.php' -printf '%u %g %p\n' | head
root root /var/www/example.com/public_html/wp-content/plugins/some-plugin/some-plugin.php
www-data www-data /var/www/example.com/public_html/wp-content/plugins/seo-pack/seo-pack.php
Meaning: A root-owned plugin file in a tree usually owned by www-data suggests someone ran an update as root (or an extraction tool did). WordPress may later fail to overwrite or clean up.
Decision: Fix ownership for the affected plugin or the whole tree (carefully), then re-run updates through the proper mechanism.
cr0x@server:~$ sudo chown -R www-data:www-data /var/www/example.com/public_html/wp-content/plugins/some-plugin.disabled
Task 11: Confirm database connectivity from WordPress config (without dumping secrets)
cr0x@server:~$ grep -E "DB_NAME|DB_USER|DB_HOST" /var/www/example.com/public_html/wp-config.php
define( 'DB_NAME', 'wpdb' );
define( 'DB_USER', 'wpuser' );
define( 'DB_HOST', '127.0.0.1' );
Meaning: You’re verifying the DB host and that you’re looking at the correct config for this site.
Decision: If the symptom looks like DB failure (“Error establishing a database connection”), test the DB service next.
Task 12: Check MySQL/MariaDB health on the host
cr0x@server:~$ sudo systemctl status mariadb --no-pager | sed -n '1,12p'
● mariadb.service - MariaDB 10.6.16 database server
Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2025-12-27 08:10:03 UTC; 1h 2min ago
Docs: man:mariadbd(8)
https://mariadb.com/kb/en/library/systemd/
Main PID: 982 (mariadbd)
Status: "Taking your SQL requests now..."
Meaning: DB is running. This doesn’t prove queries are fast, but it removes “DB is down” from the list.
Decision: If the site is still broken, return focus to PHP errors, plugins, and caching layers.
Task 13: Find the plugin’s fatal error in PHP logs (if separate)
cr0x@server:~$ sudo tail -n 60 /var/log/php8.1-fpm.log
[27-Dec-2025 09:03:44] WARNING: [pool www] child 22134 said into stderr: "PHP Fatal error: Uncaught Error: Call to undefined function some_plugin_init() in /var/www/example.com/public_html/wp-content/plugins/some-plugin/some-plugin.php:42"
Meaning: Confirms the fatal error is at PHP-FPM level, not Nginx guessing.
Decision: Keep the plugin disabled and fix the underlying mismatch (plugin version, dependency, PHP version).
Task 14: Verify the WordPress site responds locally (bypass CDN/DNS issues)
cr0x@server:~$ curl -sS -H 'Host: example.com' http://127.0.0.1/ | head -n 5
<!doctype html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
Meaning: The origin server renders HTML locally. If external users still see errors, the problem might be CDN caching, WAF rules, or load balancer health checks.
Decision: If local works and external fails, shift attention up-stack: CDN, reverse proxy, TLS termination, firewall.
Task 15: Use WP-CLI to list plugins (if possible)
cr0x@server:~$ cd /var/www/example.com/public_html && sudo -u www-data wp plugin list
+-------------------+----------+-----------+---------+
| name | status | update | version |
+-------------------+----------+-----------+---------+
| seo-pack | inactive | none | 3.2.1 |
| cache-tool | inactive | available | 2.9.0 |
| some-plugin | inactive | none | 1.4.0 |
+-------------------+----------+-----------+---------+
Meaning: You can see what’s active/inactive and what has updates pending. After a folder rename, WP-CLI may show the plugin as missing or inactive depending on state.
Decision: Use WP-CLI to re-enable carefully later, one plugin at a time, watching logs.
Task 16: Deactivate a plugin cleanly with WP-CLI
cr0x@server:~$ cd /var/www/example.com/public_html && sudo -u www-data wp plugin deactivate some-plugin
Plugin 'some-plugin' deactivated.
Success: Deactivated 1 of 1 plugins.
Meaning: WordPress now agrees the plugin is inactive. This is cleaner than directory renaming when you can run it.
Decision: If deactivation succeeds and the site recovers, you can restore the plugin directory name (if you renamed it) without reactivating.
Task 17: Check for runaway autoloaded options (common “everything got slow” cause)
cr0x@server:~$ cd /var/www/example.com/public_html && sudo -u www-data wp db query "SELECT option_name, LENGTH(option_value) AS bytes FROM wp_options WHERE autoload='yes' ORDER BY bytes DESC LIMIT 10;"
+---------------------------+--------+
| option_name | bytes |
+---------------------------+--------+
| some_plugin_cache_blob | 524288 |
| rewrite_rules | 182944 |
| wp_user_roles | 32768 |
+---------------------------+--------+
Meaning: An autoloaded half-megabyte blob is suspicious. It inflates memory and slows every request.
Decision: Keep the plugin disabled; consider deleting or de-autoloading the option after backup and careful review.
Task 18: Check PHP memory limit quickly (symptom: white screen or “Allowed memory size exhausted”)
cr0x@server:~$ php -r 'echo ini_get("memory_limit").PHP_EOL;'
128M
Meaning: 128M may be tight for heavy plugins/page builders. But increasing memory is a bandage, not a diagnosis.
Decision: If logs show memory exhaustion, you can temporarily raise memory to restore service, then fix the plugin behavior or remove it.
Common mistakes: symptoms → root cause → fix
This is the section where future-you avoids a repeat outage. These are not theoretical; these happen because WordPress is a pile of good intentions and PHP includes.
1) Symptom: “I renamed the plugin folder but nothing changed”
- Root cause: You edited the wrong WordPress instance (wrong docroot), or a deployment job restored the folder, or the site is served from a different node.
- Fix: Confirm docroot (Task 1), confirm local curl (Task 14), and check whether you’re on a load-balanced setup. Apply changes on the actual origin or all nodes.
2) Symptom: “Site shows maintenance mode forever”
- Root cause: Stuck
.maintenancefile after a failed update. - Fix: Remove
.maintenance(Task 8). Then investigate why the update failed (disk full, permissions, timeout).
3) Symptom: HTTP 502 Bad Gateway after plugin update
- Root cause: PHP-FPM is crashing or timing out due to fatal errors, memory exhaustion, or long-running requests triggered by the plugin.
- Fix: Check Nginx error log and PHP-FPM log (Tasks 6, 13). Disable the plugin; then address PHP resources or code issue.
4) Symptom: wp-admin loads, but saving settings throws 500
- Root cause: Plugin hooks on admin POST requests and fatal-errors only on that path; or WAF blocks specific payloads; or PHP max input vars/time.
- Fix: Tail logs while reproducing. Disable plugin and retest. If still failing, check WAF logs and PHP settings.
5) Symptom: Everything is “up” but painfully slow after plugin update
- Root cause: Autoloaded option bloat, expensive DB queries, or object cache thrash.
- Fix: Inspect autoload sizes (Task 17), check DB slow logs if available, and temporarily disable caching plugins to compare behavior.
6) Symptom: Only logged-in users see a white screen
- Root cause: Plugin runs only for admin/toolbars, or user-specific hooks; fatal error is hidden by error display settings.
- Fix: Tail logs while hitting wp-admin. Disable suspected admin plugins first (security, editors, builders).
7) Symptom: Plugin won’t update, or updates “succeed” but revert
- Root cause: Wrong file ownership/permissions, or immutable files, or a CI/deploy system overwriting the tree.
- Fix: Check ownership (Task 10). Confirm whether the WordPress files are managed by Git/deploy. Decide one authority: either deploy system or WP updater, not both.
8) Symptom: You fixed it, then it broke again minutes later
- Root cause: Auto-updates re-applied, a cron job re-enabled something, or cache warmed with broken code from another node.
- Fix: Disable auto-updates temporarily, check cron events, and ensure all nodes share the same plugin state.
Three corporate mini-stories from the outage trenches
Mini-story 1: The incident caused by a wrong assumption
A mid-sized company ran a WordPress-based marketing site behind a CDN and a managed load balancer. The site “went down” right after a plugin update. The on-call engineer did the standard play: SSH into the server, rename the offending plugin folder, refresh the browser.
Still down. Same 500.
The wrong assumption was subtle: they assumed there was one origin. There were two. One was the older node left behind after a migration, still registered in the load balancer pool. The plugin was disabled on the node they logged into (because that’s the hostname they remembered), but traffic was still being routed to the other node running the broken plugin code.
They eventually proved it by curling each node directly with a Host header. One node returned 200, the other returned 500. Once they disabled the plugin on the second node, the incident cleared immediately.
The post-incident fix was boring and effective: remove stale origins from the pool, and document the authoritative inventory. Also: stop relying on “the hostname you remember.” Production doesn’t care about your memory.
Mini-story 2: The optimization that backfired
A different org had a high-traffic WordPress site and wanted faster page loads. Someone installed a caching plugin and cranked settings up: aggressive HTML minification, combining scripts, deferring everything, and enabling object caching backed by a local daemon. It did make synthetic benchmarks look better.
Then a plugin update landed. The site started throwing intermittent 502s. Not consistently—just enough to be maddening. The plugin itself wasn’t the whole story: the caching layer was now caching partial error responses and serving them sporadically. Meanwhile the object cache daemon was restarting under memory pressure, causing request storms as caches re-warmed.
The team initially tried to “optimize harder”: increase cache TTLs, add more exclusions, restart services more frequently. That made it worse, because every restart amplified the thundering herd of uncached requests hitting PHP and DB.
The fix was embarrassingly simple: disable the caching plugin temporarily, stabilize, then reintroduce caching with conservative settings and actual observability. Performance work without measurement is just superstition in a nicer shirt.
Mini-story 3: The boring but correct practice that saved the day
A finance-adjacent company ran WordPress in a containerized environment. It wasn’t fancy, just disciplined: deployments were immutable images, plugin updates happened in staging first, and production only changed via a pipeline. They also kept a short retention of nightly database backups and filesystem snapshots.
One morning, a plugin update passed staging but still broke production—because production had a different PHP minor version due to a long-forgotten base image pin. The plugin called into a PHP feature not available in prod. Instant fatal error.
Instead of debugging live in production, they executed the practiced runbook: roll back the container image to the previous known-good, restore service, then compare PHP versions and plugin requirements in a calmer state. Business impact was minimized because rollback wasn’t a heroic act; it was Tuesday.
The long-term fix: align staging/prod base images, and add a pipeline check that asserts PHP version parity. The boring practice—consistent environments and rehearsed rollback—did the real work.
Facts and historical context (short, useful, slightly sobering)
- Fact 1: WordPress began in 2003 as a fork of b2/cafelog, and its plugin architecture grew with the ecosystem—powerful, but not sandboxed.
- Fact 2: Plugins execute PHP in-process; there’s no isolation boundary like a browser extension model. A plugin can break core with a single fatal error.
- Fact 3: The “White Screen of Death” became a WordPress meme because PHP fatals often produced blank output when error display was off.
- Fact 4: Automatic background updates for security releases were introduced to reduce patch lag, but they also increased the chance of unattended changes interacting badly with plugins.
- Fact 5: The
.maintenancefile exists specifically to prevent inconsistent states during updates, but it can strand you if updates crash. - Fact 6: Many outages after “plugin updates” are actually partial extracts due to low disk space or permission problems, leaving missing PHP classes.
- Fact 7: PHP 7.4 reached end-of-life in 2022, and plugins have been steadily moving their minimum requirements upward, turning old hosting stacks into time bombs.
- Fact 8: WordPress stores “active plugins” in the database, but still verifies files exist on disk, which is why folder renaming is such a reliable emergency brake.
- Fact 9: A surprisingly common performance killer is a bloated autoloaded option: it loads on many requests and punishes everything equally.
Checklists / step-by-step plan
Checklist 1: “Site is down right now” (stabilize first)
- Capture the symptom: HTTP status (200/500/502/503), maintenance mode message, white screen, wp-admin accessible or not.
- Check logs: web server error log and PHP-FPM log for a fatal line pointing to a plugin file.
- Disable the likely plugin: rename its folder under
wp-content/plugins. - If unsure, disable all plugins: rename
pluginstoplugins.disabledand create an emptypluginsdirectory. - Remove stuck maintenance mode: delete
.maintenanceif present. - Verify with curl: confirm HTTP 200 and basic HTML from origin.
- Confirm wp-admin login: if admin works, your next job is controlled restoration.
Checklist 2: Controlled restoration (don’t re-break it)
- Re-enable plugins one at a time: move one plugin folder back (or activate via WP-CLI), then test and check logs.
- Watch for hidden failures: test a dynamic endpoint (checkout, contact form, search) not just the homepage.
- Clear caches deliberately: page cache, object cache, CDN cache (in that order). Confirm the origin is correct first.
- Lock down auto-updates temporarily: stop the system from reintroducing the bad version.
- Record evidence: keep the fatal error stack trace and the plugin version; you’ll need it for rollback or vendor support.
Checklist 3: Prevention (turn pain into process)
- Keep staging aligned with production: same PHP version, same extensions, same caching stack.
- Backups you can restore: database + uploads + plugin/theme code, tested restore, not just “we have backups.”
- Change control for plugins: schedule updates, record versions, and avoid “auto-update everything” unless you have rollback muscle.
- Observability: centralize logs, keep error logs readable, and alert on spikes in 5xx and PHP fatals.
Joke #2: The fastest way to learn WordPress internals is a plugin outage. The second fastest is reading this before the outage.
FAQ
1) If I rename a plugin folder, will I lose plugin settings?
Usually no. Most plugin settings live in the database. Renaming only prevents code from loading. But some plugins run uninstall routines on deactivation; folder rename avoids that, which is often safer during recovery.
2) What if wp-admin is also down and I can’t log in?
That’s normal in plugin fatals because WordPress can’t bootstrap. Use filesystem disable (rename plugin folder or plugins directory) or WP-CLI if it can load.
3) Should I delete the plugin folder?
No, rename it. Deletion destroys evidence and makes rollback harder. Rename is reversible and fast.
4) Can I disable a plugin from the database directly?
You can, by editing the active_plugins option, but it’s a sharp tool. If you’re already on SSH, folder rename is safer and faster under pressure. Use DB edits only when you understand serialized PHP arrays and have a backup.
5) Why does disabling all plugins sometimes still not fix the site?
Because the plugin wasn’t the only failure. Common culprits: stuck .maintenance, PHP-FPM down, disk full, database connection issues, or theme-level fatals. Disabling plugins is a test, not a religion.
6) I disabled the plugin but the site still shows the error page. Now what?
Check whether you’re seeing cached error responses (CDN/page cache). Verify locally from the origin with curl. Then clear caches. Also confirm you changed the correct node in a load-balanced setup.
7) How do I figure out which plugin caused it if I don’t know?
Sort plugin directories by modification time (Task 2), then tail logs for the fatal stack trace (Task 6). If you still can’t tell, disable all plugins and re-enable one at a time until it breaks again.
8) Is WP-CLI always safe to use during an outage?
It’s safe when you run it as the correct user and it can bootstrap WordPress. If the fatal happens before WP loads, WP-CLI may also fail. Keep the folder-rename method as your no-dependencies fallback.
9) What’s the difference between a 500 and a 502 in this context?
500 often means the web server got a response but it’s an internal error (or PHP emitted a fatal and the server mapped it). 502 often means the reverse proxy couldn’t get a valid response from PHP-FPM upstream (crash, timeout, bad gateway). In practice: both send you to logs.
10) Should I increase PHP memory limit to fix it?
Only if logs show memory exhaustion, and only as a temporary stabilizer. If a plugin update suddenly needs 2× memory, you’re paying for someone else’s bug with your server budget.
Conclusion: next steps that prevent repeat pain
To recover fast: disable the plugin by renaming its folder (or the whole plugins directory), remove a stuck .maintenance file, verify with curl, and read logs until the fatal line makes sense. Then re-enable plugins one by one, with logs open, not vibes.
Next steps that actually move the needle:
- Stop unattended plugin roulette: schedule updates and require a rollback plan.
- Make staging match production: PHP version parity prevents the “worked in staging” lie.
- Improve your observability: centralized logs and 5xx alerts turn mystery outages into short incidents.
- Practice rollback: the best time to learn restore procedures is not during a revenue-impacting outage.