Incident Overview
A small-business site went down overnight with no deployment, no update clicked, and no one logged in. Every URL — front end and /wp-admin — returned a blank white page with HTTP 500 and zero bytes of HTML. The trigger: the host’s fleet-wide, mandatory migration from PHP 7.4 (end-of-life) to PHP 8.2, applied automatically at 02:00.
The blank screen is the defining trait of a fatal PHP error with display suppressed: the process died before emitting any output. The page is empty, but the error log is not.
Raw Diagnostic Logs
display_errors off (correct for production), so the evidence lives in the log:
$ tail -3 /home/account/logs/error_log
[26-Jul-2026 02:04:11 UTC] PHP Fatal error: Uncaught Error: Call to undefined
function create_function() in /home/account/public_html/wp-content/themes/
legacy-biz-child/inc/widgets.php:214
Stack trace:
#0 /home/account/public_html/wp-settings.php(675): include()
One line tells the whole story: file, line, and the removed API. create_function() was deprecated in PHP 7.2 and removed in PHP 8.0 — the theme had been shipping a time bomb for years, armed the moment the host pulled 7.4.
A quick sweep for the same pattern before fixing anything, so the site doesn’t crash again one file later:
$ grep -rn "create_function\|each(" wp-content/themes/legacy-biz-child/ \
wp-content/plugins/ --include="*.php" | grep -v vendor | cut -d: -f1 | sort -u
wp-content/themes/legacy-biz-child/inc/widgets.php
wp-content/themes/legacy-biz-child/inc/customizer.php
Two files, five call sites total — small enough to patch properly rather than abandoning the theme.
Forensic Root Cause Analysis
The failure chain:
- Host removes PHP 7.4 (EOL) and force-migrates all accounts to 8.2 — legitimate and announced, but announced to an inbox nobody monitored.
- The active child theme registers widgets via
create_function(), an API removed in PHP 8.0. - WordPress loads the theme on every request, including admin requests — so the fatal error also locked the owner out of the dashboard that could have switched themes.
- WordPress’s built-in recovery mode emails went to a defunct address, so the “site is having technical difficulties” lifeline was never seen.
Root cause: unmaintained theme code using a removed API, with the upgrade risk invisible because no compatibility scan had ever run against the site.
Remediation & Command Log
Backup, then restore service in the safest order — WP-CLI works even when the site’s pages don’t:
tar -czf /home/account/pre-fix-$(date +%F).tar.gz public_html/
mariadb-dump --single-transaction site_db | gzip > /home/account/pre-fix-db.sql.gz
# Confirm the failure is theme-scoped: switch to a bundled default theme
wp theme activate twentytwentyfour
curl -s -o /dev/null -w "%{http_code}\n" https://example-site.com/
# 200 — site is back on a fallback theme within minutes
With the site up, patch the five call sites offline. Representative diff:
// Before — removed in PHP 8.0
add_action('widgets_init', create_function('', 'register_widget("Legacy_CTA_Widget");'));
// After — anonymous function, PHP 8.x-safe
add_action('widgets_init', function () {
register_widget('Legacy_CTA_Widget');
});
Lint every changed file against the new runtime before reactivating:
for f in inc/widgets.php inc/customizer.php; do php -l "wp-content/themes/legacy-biz-child/$f"; done
wp theme activate legacy-biz-child
curl -s -o /dev/null -w "%{http_code}\n" https://example-site.com/
# 200 — original theme restored, look and feel unchanged
Preventative Hardening
- Ran the full codebase through PHPCompatibility (PHP_CodeSniffer ruleset) targeting PHP 8.2; patched every remaining deprecation warning, not just the fatals.
- Fixed the recovery-mode email so the next fatal error reaches a monitored inbox:
// wp-config.php
define('RECOVERY_MODE_EMAIL', 'ops@client-domain.com');
- Registered the hosting account’s notification address to a shared, monitored mailbox — the migration notice had gone unread for six weeks.
- Left the client a one-page upgrade-readiness checklist: how to spin up the host’s staging clone and run the compatibility scan before any future PHP version bump.
Details in this post-mortem are anonymized and composited from recurring incidents of the same failure class. The logs and commands are representative of the actual diagnostic path. Staring at a blank page right now? Our white screen recovery service starts with your error log, not guesswork.