How a WordPress site whose every error blamed a different plugin was diagnosed and recovered by eliminating variables until the real fault, hiding in shared database and locale state, had nowhere left to go.
This one is my own site, which means I can show you the real errors and the real SQL, with nothing sanitised away.
Project
Vivir Europa, my own travel site
Scope
Debugging · database forensics · isolation testing · recovery
Symptoms
Content creation failing · comments missing · wp-admin locked
Constraint
Live site, no staging, ambiguous evidence
Documented sequence
≈4.5h from first symptom to confirmed recovery
Every error blamed a different plugin
On the evening of 23 December 2024, my own travel site, Vivir Europa, started failing in ways that made no sense together. WordPress couldn’t create new pages or posts. Three pending comments existed but wouldn’t appear. Scheduled background actions were crashing. And within ninety minutes, wp-admin locked me out entirely.
The debug log had plenty to say, and all of it was misleading. The first database error pointed at WPForms. Then a fatal error pointed at WP Rocket. Then another pointed at Ad Inserter. Three different plugins, three different stack traces, one evening.
This is the situation most WordPress owners know and fear: the site is broken, every error names a different suspect, and the obvious move (update, reinstall, or delete whichever plugin the last error mentioned) is a coin flip that can make things worse.
Error en la base de datos de WordPress: [Duplicate entry '0' for key 'PRIMARY']
The first recorded database error. New records were being created with ID 0, colliding with each other.
The stack traces were symptoms, not causes
Stack traces
WPForms · WP Rocket · Ad Inserter
Shared state
database schema + locale option
Every trace named a different plugin. The fault lived in state they all shared.
Each plugin appeared in a trace because it happened to be the caller at the moment WordPress hit the underlying fault, not because it created the fault.
Two separate defects were hiding underneath. First, core tables had stopped generating IDs: wp_posts and wp_comments were assigning ID 0 to every new record, so the second insert always collided with the first. That single defect explained the failed page creation, the invisible comments, and the crashing background actions: three “unrelated” symptoms, one mechanism.
Second, the site’s locale state was invalid: WordPress’s translation loader was receiving an object where it expected a locale string, producing a fatal that surfaced through whichever plugin loaded translations first.
Eliminate variables until the fault has nowhere left to hide
- Enabled WordPress debugging and read the errors as evidence, not verdicts.
- Repaired the confirmed identifier defects. Restoring AUTO_INCREMENT behaviour on wp_posts brought page and post creation back. The comments table had the same defect and was repaired the same way.
- Restored a previous-day backup when wp-admin remained locked. It didn’t resolve the fatal, which was itself diagnostic: the problem survived the restore.
- Isolated everything. Renamed the entire plugins directory, renamed the cache directory, and stripped WP Rocket’s 130 lines of rewrite rules from .htaccess, preserving the original file as a backup.
- The fatal persisted with everything disabled, now pointing at WordPress core itself. This was the decisive elimination: no active plugin, no cache, no rewrite rules, same crash. The fault had to live in shared data.
- Reset the locale option with a one-line UPDATE. Site and wp-admin came back immediately.
- Reintroduced plugins gradually the next morning, leaving two redundant ones permanently disabled.
Object of class stdClass could not be converted to string wp-includes/l10n.php:959
The fatal that survived every plugin being disabled: the proof the problem was in shared WordPress state, not in any of the plugins the stack traces had named.
UPDATE wp_options SET option_value = '' WHERE option_name = 'WPLANG';
The one-line fix, once four hours of elimination had proven where the fault actually lived.
19:36First recorded symptom: WordPress cannot create pages or posts
19:56Debugging enabled; duplicate-ID database errors surface through WPForms’ scheduler
20:20wp_posts identifier defect repaired; content creation restored; wp_comments repaired next
20:56wp-admin locks out; a fatal error appears, first blaming WP Rocket, later Ad Inserter
21:08Previous-day backup restored; the fatal survives it
23:55All plugins, cache, and rewrite rules disabled; the fatal persists in WordPress core’s localisation path
23:56Invalid locale state reset with a one-line UPDATE
00:07Recovery confirmed: front end and wp-admin working; plugins reintroduced gradually next morning
Times are documented conversation timestamps (UTC) from the incident record, not uptime monitoring.
| Scenario | Before | After |
|---|---|---|
| Content creation | Every new page or post failed with a duplicate-ID collision | Working, identifier generation repaired in wp_posts |
| Comments | Pending comments invisible | Comments table repaired with the same fix |
| Site access | Fatal error on front end and wp-admin | Both restored after resetting invalid locale state |
| Diagnosis | Three plugins blamed by stack traces | All three cleared by isolation; fault located in shared state |
Tempting moves, set aside on purpose:
01Reinstalling whichever plugin the latest stack trace blamed
02Deleting data or tables “to start clean”
03Stopping at the first plausible culprit
04Claiming a root cause the evidence doesn’t support
→The investigation recovered the installation without conclusively determining what originally corrupted the schema and locale state. Saying so is part of the diagnosis: knowing what you haven’t proven is what stops you breaking things twice.
My role: debugging configuration · database schema forensics · isolation testing across plugins, cache, and rewrite rules · recovery execution · staged reactivation
Every stack trace named a different plugin. The fault lived in state they all shared.
WordPress failing with errors that blame a different plugin every time?
I find the real fault before touching anything you can’t undo.
2 retainer spots available