Pantalla blanca de la muerte de WordPress (WSOD): 12 comprobaciones que realmente funcionan

¿Te fue útil?

La Pantalla Blanca de la Muerte es la manera en que WordPress dice “algo explotó” mientras se niega a decirte dónde cayeron los fragmentos. Los clientes ven una página en blanco. Tu monitorización muestra “200 OK”. Tu cerebro en guardia recuerda su propia mortalidad.

Este es el playbook que desearía que más equipos siguieran: triage rápido primero, luego comprobaciones disciplinadas que convierten el misterio en una única causa raíz que puedes arreglar y evitar.

Guía de diagnóstico rápido (primeros 10 minutos)

La velocidad importa, pero adivinar es más lento que leer el registro correcto una vez. El objetivo es encontrar el cuello de botella: ¿la falla ocurre antes de que se ejecute PHP, dentro de PHP, o después de PHP (base de datos/caché/almacenamiento)?

Minuto 0–2: confirma qué significa “blanco”

  • Comprueba el estado HTTP y las cabeceras. Un 500 con cuerpo vacío es distinto de un 200 que devuelve espacios en blanco.
  • Compara la página de inicio con wp-admin. Si wp-admin carga, suele ser tema/plugin de frontend, no un fallo global del runtime.
  • Evita CDN y caches. Si el origen está bien y el edge está en blanco, estás depurando el sistema equivocado.

Minuto 2–5: lee los registros como un adulto

  • Registro de errores del servidor web (Nginx/Apache) para fallos upstream y timeouts.
  • Registro de PHP-FPM / registro de errores de PHP para errores fatales, agotamiento de memoria, problemas con el opcode cache.
  • Fatal a nivel de aplicación mediante el log de depuración de WordPress si puedes activarlo de forma segura.

Minuto 5–10: aisla plugins/temas sin tocar código

  • Desactiva todos los plugins (WP-CLI o renombrando el directorio) y prueba de nuevo.
  • Cambia a un tema por defecto conocido y estable.
  • Si sigue en blanco, deja de culpar “un plugin” y mira incompatibilidades de versión PHP, extensiones faltantes, conectividad BD, disco y memoria.

Un modelo mental útil: WSOD rara vez significa “WordPress está caído.” Normalmente es “PHP encontró un fatal y el buffering produjo nada” o “el runtime no puede leer/escribir archivos necesarios y falla en mitad del proceso.”

Algunos datos (y breve historia) sobre WSOD

  • WSOD es anterior a WordPress. El término se popularizó en el ecosistema PHP cuando los errores fatales se suprimían en producción, dejando salida en blanco.
  • WordPress solía fallar en silencio por defecto. Las primeras configuraciones a menudo tenían display_errors desactivado sin registro centralizado, haciendo que WSOD fuera efectivamente “normal”.
  • “El Modo de Recuperación” es relativamente nuevo. WordPress introdujo protección/recuperación ante errores fatales (era 5.2) que puede enviar correos a los admins y permitir desactivar un plugin/tema roto. Ayuda, pero no es omnisciente.
  • WSOD puede ser un 200 OK. Muchas fallas ocurren después de enviar las cabeceras o se manejan de manera que devuelven un body vacío con estado de éxito—por eso las comprobaciones de uptime mienten.
  • OPcache hizo WSOD mejor y peor. Mejora el rendimiento, pero el bytecode obsoleto después de un despliegue puede seguir ejecutando código antiguo incluso cuando los archivos cambiaron.
  • PHP moderno es más estricto. Actualizar PHP puede convertir “advertencias que ignoraste años” en fatales debido a funciones eliminadas o tipado más estricto.
  • El agotamiento de memoria sigue siendo una causa principal. Especialmente con page builders, grandes instalaciones de WooCommerce y plugins “útiles” que hacen operaciones costosas en cada petición.
  • Los fallos de almacenamiento a menudo se disfrazan de WSOD. Disco lleno, sistema de archivos en solo lectura o NFS lento pueden provocar que sesiones/subidas/cache fallen, resultando en páginas en blanco.
  • Los CDNs pueden cachear vacío. Si el origen devuelve brevemente un 200 en blanco, el edge puede servir esa blancura a todos hasta que expire.

Una cita que todo incidente WSOD prueba en silencio: Todo falla, todo el tiempo. — Werner Vogels

Las 12 comprobaciones que realmente funcionan (con comandos, salidas, decisiones)

Cada comprobación abajo es una tarea real: un comando que puedes ejecutar, qué significa la salida y la decisión que tomas. Hazlas en orden a menos que ya tengas una pistola humeante.

Broma #1: WSOD es como una reunión sin agenda: todos están presentes, nada pasa y de algún modo sigues perdiendo dinero.

Comprobación 1) Confirma el modo de fallo con curl (estado, cabeceras, tamaño del body)

cr0x@server:~$ curl -sS -D- -o /tmp/body.html -w "\nstatus=%{http_code} size=%{size_download} time=%{time_total}\n" https://example.com/ | head -n 20
HTTP/2 200
date: Thu, 26 Dec 2025 14:21:09 GMT
content-type: text/html; charset=UTF-8
cache-control: max-age=0, must-revalidate
server: nginx

status=200 size=0 time=0.312

Qué significa: Un 200 con size=0 es comportamiento clásico de WSOD: la solicitud tuvo éxito a nivel HTTP, pero no generó body (o se truncó).

Decisión: Trátalo como una falla de aplicación/runtime, no como “el servidor web está caído.” Pasa a los logs y a PHP-FPM.

Comprobación 2) Evita CDN / caché de borde para probar el origen

cr0x@server:~$ curl -sS -H "Cache-Control: no-cache" -H "Pragma: no-cache" -D- -o /dev/null https://example.com/
HTTP/2 200
date: Thu, 26 Dec 2025 14:21:31 GMT
content-type: text/html; charset=UTF-8
cf-cache-status: HIT
server: cloudflare

Qué significa: El edge está sirviendo contenido cacheado (quizás la blancura cacheada). Tu petición “no-cache” no forzó al origen.

Decisión: Prueba el origen directamente apuntando al IP/host header del origen o a la dirección del LB interno. Si el origen está bien, purga la cache del edge; si el origen está roto, deja de mirar el CDN.

Comprobación 3) Mira primero los errores del servidor web (ejemplo Nginx)

cr0x@server:~$ sudo tail -n 80 /var/log/nginx/error.log
2025/12/26 14:20:58 [error] 23144#23144: *9181 FastCGI sent in stderr: "PHP message: PHP Fatal error:  Uncaught Error: Call to undefined function mysql_connect() in /var/www/html/wp-content/plugins/legacy-db/legacy.php:41" while reading response header from upstream, client: 203.0.113.10, server: example.com, request: "GET / HTTP/2.0", upstream: "fastcgi://unix:/run/php/php8.2-fpm.sock:", host: "example.com"

Qué significa: Esto es oro: un error fatal dentro de un plugin que llama a una función eliminada. PHP nunca produjo una respuesta válida.

Decisión: Desactiva ese plugin inmediatamente. Luego planifica una corrección de código o un reemplazo. También revisa por qué esto llegó a producción (más adelante hablamos de eso).

Comprobación 4) Revisa la salud del servicio PHP-FPM y caídas recientes

cr0x@server:~$ sudo systemctl status php8.2-fpm --no-pager
● php8.2-fpm.service - The PHP 8.2 FastCGI Process Manager
     Loaded: loaded (/lib/systemd/system/php8.2-fpm.service; enabled)
     Active: active (running) since Thu 2025-12-26 14:00:01 UTC; 21min ago
   Main PID: 1109 (php-fpm8.2)
      Tasks: 19 (limit: 18962)
     Memory: 214.5M
        CPU: 1min 42.110s
     CGroup: /system.slice/php8.2-fpm.service
             ├─1109 "php-fpm: master process (/etc/php/8.2/fpm/php-fpm.conf)"
             └─1132 "php-fpm: pool www"

Qué significa: PHP-FPM está arriba. Eso no significa que esté sano; sólo que está vivo. Aún necesitas inspeccionar logs por caídas de workers, max children, solicitudes lentas.

Decisión: Si PHP-FPM está caído o inestable, arregla eso primero (config, memoria, fallos de segmentación, problemas de paquetes). Si está arriba, continúa con los logs.

Comprobación 5) Lee el log de PHP-FPM buscando patrones fatales (memoria, timeouts, segfaults)

cr0x@server:~$ sudo tail -n 120 /var/log/php8.2-fpm.log
[26-Dec-2025 14:20:58] WARNING: [pool www] child 1733 said into stderr: "PHP Fatal error:  Allowed memory size of 268435456 bytes exhausted (tried to allocate 4096 bytes) in /var/www/html/wp-includes/class-wpdb.php on line 2345"
[26-Dec-2025 14:21:03] WARNING: [pool www] child 1735 exited on signal 11 (SIGSEGV) after 2.412340 seconds from start
[26-Dec-2025 14:21:03] NOTICE: [pool www] child 1741 started

Qué significa: Pueden existir dos problemas separados: agotamiento de memoria (habitualmente determinístico por solicitud) y segfaults (a menudo bugs en extensiones, OPcache o memoria corrupta). Ambos pueden producir WSOD.

Decisión: Para agotamiento de memoria: identifica la solicitud/plugin/tema culpable; aumenta límites sólo después de entender por qué. Para segfaults: revisa extensiones (Redis, Imagick), OPcache, versión de PHP; considera revertir o desactivar la extensión.

Comprobación 6) Habilita el registro de depuración de WordPress de forma segura (no display_errors)

En producción quieres registros, no salida pública de errores. Edita wp-config.php y registra en archivo. Luego reproduce la solicitud una vez.

cr0x@server:~$ sudo -u www-data sed -n '1,120p' /var/www/html/wp-config.php | tail -n 20
define('WP_DEBUG', false);
define('WP_DEBUG_LOG', false);
define('WP_DEBUG_DISPLAY', false);

Cambia (temporalmente) a:

cr0x@server:~$ sudo -u www-data perl -0777 -pe 's/define\(\x27WP_DEBUG\x27,\s*false\);/define(\x27WP_DEBUG\x27, true);/; s/define\(\x27WP_DEBUG_LOG\x27,\s*false\);/define(\x27WP_DEBUG_LOG\x27, true);/; s/define\(\x27WP_DEBUG_DISPLAY\x27,\s*false\);/define(\x27WP_DEBUG_DISPLAY\x27, false);/' -i /var/www/html/wp-config.php

Luego visita el sitio y lee:

cr0x@server:~$ sudo tail -n 80 /var/www/html/wp-content/debug.log
[26-Dec-2025 14:22:15 UTC] PHP Fatal error:  Uncaught TypeError: strpos(): Argument #1 ($haystack) must be of type string, null given in /var/www/html/wp-content/themes/custom/functions.php:912
Stack trace:
#0 /var/www/html/wp-content/themes/custom/functions.php(912): strpos()
#1 /var/www/html/wp-includes/class-wp-hook.php(324): theme_filter()

Qué significa: El código del tema está fallando. Eso puede dejar en blanco el front end mientras wp-admin aún funciona.

Decisión: Cambia el tema ahora; arregla el tema después de restaurar el servicio. Revierta las opciones de depuración tras capturar el error (o mantén el registro, pero haz rotación).

Comprobación 7) Desactiva todos los plugins usando WP-CLI (rápido, reversible)

cr0x@server:~$ cd /var/www/html
cr0x@server:~$ sudo -u www-data wp plugin list --status=active
+---------------------+--------+-----------+---------+
| name                | status | update    | version |
+---------------------+--------+-----------+---------+
| redis-cache         | active | none      | 2.5.2   |
| legacy-db           | active | available | 1.3.1   |
| woo-commerce        | active | none      | 8.5.0   |
+---------------------+--------+-----------+---------+
cr0x@server:~$ sudo -u www-data wp plugin deactivate --all
Plugin 'redis-cache' deactivated.
Plugin 'legacy-db' deactivated.
Plugin 'woo-commerce' deactivated.
Success: Deactivated 3 of 3 plugins.

Qué significa: Has eliminado la variable más grande: el código de plugins. Si WSOD desaparece, reactiva uno por uno (búsqueda binaria si hay muchos).

Decisión: Si desactivar plugins lo arregla: reactiva hasta que vuelva a fallar; entonces parchea/reemplaza el culpable. Si no se arregla: mira tema/runtime/BD/almacenamiento.

Comprobación 8) Cambia a un tema por defecto sin la interfaz admin

Si el front end está caído pero no puedes entrar a wp-admin, cambiar temas vía CLI es limpio.

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

Qué significa: Has reemplazado la ruta de ejecución que renderiza la mayoría de las páginas. Los WSOD frecuentemente viven en functions.php o en el archivo “útil” y enmarañado del tema.

Decisión: Si esto restaura el sitio, deja el tema por defecto activo mientras arreglas el tema personalizado. Tu equipo de marca sobrevivirá.

Comprobación 9) Verifica la versión de PHP, módulos cargados y extensiones faltantes

cr0x@server:~$ php -v
PHP 8.2.12 (cli) (built: Nov  8 2025 10:12:34) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.12, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.12, Copyright (c), by Zend Technologies
cr0x@server:~$ php -m | egrep -i 'mysqli|pdo_mysql|imagick|redis|opcache'
mysqli
PDO
pdo_mysql
redis
Zend OPcache

Qué significa: Lo básico está presente. Si te falta mysqli o pdo_mysql, WordPress puede fallar gravemente. Si falta imagick, algún plugin/tema podría provocar un fatal si asume que existe.

Decisión: Si falta una extensión requerida, instálala o cambia el plugin/tema que la asume. También: asegúrate de que las versiones de PHP-FPM y CLI coincidan; las discrepancias crean “funciona en CLI, falla en web”.

Comprobación 10) Confirma límites de memoria en capas PHP y WordPress

cr0x@server:~$ php -r 'echo "memory_limit=".ini_get("memory_limit").PHP_EOL;'
memory_limit=256M
cr0x@server:~$ grep -R "WP_MEMORY_LIMIT" -n /var/www/html/wp-config.php
42:define('WP_MEMORY_LIMIT', '128M');
43:define('WP_MAX_MEMORY_LIMIT', '256M');

Qué significa: WordPress puede limitar la memoria a un valor inferior al setting global de PHP. Las solicitudes de admin usan WP_MAX_MEMORY_LIMIT; el frontend usa WP_MEMORY_LIMIT. Un WSOD que solo afecta a wp-admin puede ser el caso inverso.

Decisión: Si estás alcanzando fatales por memoria, aumenta temporalmente WP_MEMORY_LIMIT para que coincida con PHP, pero no te quedes ahí. Encuentra la consulta pesada, el bucle infinito o el plugin que hace trabajo sin límites. Más memoria no es una solución; es un parche.

Comprobación 11) Valida la conectividad a la base de datos y busca “too many connections”

WordPress puede quedarse en blanco cuando las llamadas a BD fallan a mitad del render, especialmente si los errores están suprimidos y el tema no maneja nulos.

cr0x@server:~$ mysql -h 127.0.0.1 -u wpuser -p -e "SELECT 1;"
Enter password:
1
1
cr0x@server:~$ mysql -h 127.0.0.1 -u root -p -e "SHOW STATUS LIKE 'Threads_connected'; SHOW VARIABLES LIKE 'max_connections';"
Enter password:
Threads_connected	148
max_connections	150

Qué significa: Estás rozando el techo de conexiones. Cuando el sitio se dispara, los workers PHP se encolan y la BD rechaza conexiones. Dependiendo del manejo de errores, puede aparecer WSOD.

Decisión: Corto plazo: reduce la concurrencia (PHP-FPM pm.max_children), o aumenta max_connections si el host puede soportarlo. Largo plazo: optimiza consultas, añade caché correctamente y deja de ejecutar “analíticas lentas” en el path de solicitud.

Comprobación 12) Sanidad del almacenamiento: disco lleno, inodos, permisos y montajes en solo lectura

Los problemas de almacenamiento son los asesinos silenciosos de las apps PHP: sesiones que no se pueden escribir, cache que no se actualiza, subidas que fallan y rutas de código que hacen cosas extrañas cuando las operaciones de archivo devuelven false.

cr0x@server:~$ df -h /var/www /tmp
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        40G   39G  160M 100% /
tmpfs           1.0G  1.0G     0 100% /tmp
cr0x@server:~$ df -i /
Filesystem     Inodes IUsed  IFree IUse% Mounted on
/dev/vda1     262144 262144     0  100% /
cr0x@server:~$ mount | grep ' on / '
/dev/vda1 on / type ext4 (ro,relatime,errors=remount-ro)

Qué significa: Triple golpe: disco lleno, inodos agotados y el sistema de archivos remontado en solo lectura. WordPress no va a manejar esto con gracia; simplemente fallará al escribir archivos críticos y puede presentarse como WSOD.

Decisión: Restaura la capacidad de escritura y libera espacio primero. Elimina logs, limpia directorios temporales, rota correctamente y averigua por qué el filesystem cambió a solo lectura (errores de disco subyacente, kernel). No pierdas tiempo reinstalando plugins mientras tu disco está en llamas.

Comprobación adicional) OPcache: cuando los despliegues “suceden” pero el código no cambia

Esta es tan común en producción que merece un lugar incluso si hace la lista “12 más un extra.” Si solo puedes tener doce comprobaciones, reemplaza la que menos uses por esta.

cr0x@server:~$ php -r 'echo "opcache.enable=".ini_get("opcache.enable").PHP_EOL; echo "opcache.validate_timestamps=".ini_get("opcache.validate_timestamps").PHP_EOL; echo "opcache.revalidate_freq=".ini_get("opcache.revalidate_freq").PHP_EOL;'
opcache.enable=1
opcache.validate_timestamps=0
opcache.revalidate_freq=2

Qué significa: Con la validación de timestamps desactivada, PHP puede no detectar cambios de código hasta que FPM se reinicie. Eso puede mantener una versión rota ejecutándose incluso después de “arreglarla”.

Decisión: En modelos de despliegue inmutables esto puede ser aceptable si reinicias PHP-FPM en el deploy. Si no lo haces, habilita la validación o añade un paso de recarga explícita. Consistencia operativa vence a la astucia.

Broma #2: “Funciona en mi portátil” es adorable. Producción no hace adorable.

Tres microhistorias corporativas desde el terreno

Microhistoria 1: El incidente causado por una suposición errónea (la actualización de PHP “estaba bien”)

Una compañía mediana gestionaba un sitio de WordPress con mucho contenido detrás de un proxy inverso Nginx. También tenían una granja de micrositios de marketing separada. Un martes tranquilo actualizaron la imagen base de todos los servicios PHP, pasando de PHP 7.4 a PHP 8.2. Estaba planeado, aprobado y “probado”.

La suposición errónea fue sencilla: si la página de inicio de staging carga, producción cargará. Su entorno de staging tenía un conjunto de plugins distinto—por licencias. El plugin legacy que manejaba una integración con una base de datos antigua no estaba instalado en staging, y nadie lo notó porque “ya no debía importar”. Importaba.

Producción empezó a devolver un 200 en blanco para la página de inicio. La monitorización se mantuvo verde porque su health check hacía hit a /robots.txt, que era estático. Llegaron tickets de soporte. El ingeniero on-call vio el 200 y al principio culpó al CDN. Diez minutos se perdieron en purgas de cache y redeploys.

La solución fue rápida una vez que miraron los errores de Nginx: un fatal por una función PHP eliminada. Desactivaron el plugin vía WP-CLI, restauraron el servicio y luego lo reemplazaron por una integración soportada.

La prevención fue menos glamorosa: su política de “paridad de staging” ahora requería la misma lista de plugins (aunque configurados de forma distinta), y las actualizaciones requerían una transacción sintética que tocara endpoints dinámicos de WordPress, no archivos estáticos.

Microhistoria 2: La optimización que salió mal (cache de objetos sin salvaguardas)

Un equipo empresarial tenía un sitio WordPress que se disparaba durante comunicados de prensa. Alguien propuso caché de objetos en Redis para reducir carga BD. Buen instinto. Lo desplegaron rápido, celebraron la caída de CPU en BD y siguieron con el siguiente fuego.

Semanas después, una actualización de plugin introdujo un bug sutil: cacheaba un gran grafo de objetos PHP bajo una clave que variaba por user-agent y algunos parámetros de query. Las claves explotaron. La memoria de Redis se llenó, la expulsión se volvió agresiva y la latencia subió. Bajo carga, las peticiones PHP empezaron a agotar tiempo esperando llamadas a Redis.

Desde fuera, el sitio parecía WSOD: páginas en blanco o medio renderizadas. Internamente, Nginx mostraba timeouts upstream. PHP-FPM tenía muchos workers activos bloqueados. La base de datos estaba bien, lo que confundió al equipo porque “resolvimos BD.” No habían resuelto el camino de la petición; solo habían movido el cuello de botella a otra caja.

La reversión fue desactivar el caché de objetos inmediatamente (renombrar el drop-in), luego reintroducirlo con restricciones: TTLs sensatos, límites de memoria, disciplina de claves y la regla de que bugs de cache son outages de producción, no “problemas de rendimiento”.

La lección: el caché es una herramienta afilada. Si la agitas en una sala llena, alguien sangra.

Microhistoria 3: La práctica aburrida pero correcta que salvó el día (logs, rotación y un canario)

Un equipo de servicios financieros gestionaba WordPress para una base de conocimientos. Nada exótico, mucha compliance. Sus prácticas no eran emocionantes: logs centralizados, rotación estricta, checklist de despliegue y un host canario que recibía tráfico de usuarios internos primero.

Un día, una actualización de tema introdujo un error fatal en una plantilla de página poco usada. El host canario empezó a registrar el fatal inmediatamente. Como los logs estaban centralizados, el on-call no necesitó heroicas SSH; vio el stack trace exacto en un dashboard y revertió el paquete del tema.

Usuarios externos nunca vieron WSOD. El cambio fue revertido antes de la etapa de rollout público. Sin drama, sin sala de guerra, sin “quizás sea DNS”.

Esta es la parte que la gente odia: la solución correcta no fue un comando ingenioso. Fue proceso y observabilidad aburridos. Lo aburrido es una característica cuando eres responsable del uptime.

Errores comunes: síntoma → causa raíz → solución

1) Página en blanco sólo en la página de inicio

  • Síntoma: / está en blanco; /wp-admin funciona.
  • Causa raíz: Crash en template del tema, hook de plugin sólo del frontend, o un fatal en un shortcode usado en la página de inicio.
  • Solución: Cambia el tema vía WP-CLI; desactiva plugins de frontend; revisa el log de depuración para el stack trace; reintroduce cambios uno a la vez.

2) Pantalla blanca tras actualizar un plugin

  • Síntoma: El sitio queda en blanco inmediatamente después de actualizar un plugin.
  • Causa raíz: Fatal por incompatibilidad de versión PHP, extensión faltante o mal autoloader/duplicación de clases.
  • Solución: Desactiva el plugin vía WP-CLI; verifica la versión de PHP; revierte el plugin; prueba la actualización en staging con paridad.

3) Pantalla blanca sólo para usuarios logueados

  • Síntoma: Usuarios anónimos ven el sitio; admins ven WSOD.
  • Causa raíz: Plugins solo de admin, widgets del dashboard o diferencias de límite de memoria (WP_MAX_MEMORY_LIMIT).
  • Solución: Aumenta temporalmente la memoria de admin; desactiva plugins de admin; revisa logs PHP-FPM por agotamiento de memoria; perfila páginas lentas de admin.

4) Pantalla blanca intermitente bajo carga

  • Síntoma: Funciona a veces; queda en blanco durante picos.
  • Causa raíz: Agotamiento de workers PHP-FPM, timeouts upstream, límites de conexiones BD, latencia de Redis o almacenamiento lento.
  • Solución: Revisa timeouts de Nginx upstream, pm.max_children de PHP-FPM, Threads_connected de BD, latencia de Redis. Reduce concurrencia u optimiza el camino lento.

5) WSOD comenzó “después de limpiar caches”

  • Síntoma: Limpiar cache parece desencadenar páginas en blanco.
  • Causa raíz: Plugin de cache escribe en disco/tmp, pero el disco está lleno o el filesystem es de solo lectura; o los permisos en wp-content son incorrectos.
  • Solución: Revisa disco/inodos, flags de montaje, permisos en wp-content; arregla almacenamiento primero y luego reconstruye caches.

6) WSOD tras habilitar “endurecimiento de seguridad”

  • Síntoma: El sitio queda en blanco tras habilitar una regla WAF, plugin de hardening o cambiar permisos de archivos.
  • Causa raíz: Bloqueo de admin-ajax/admin-post, bloqueo de endpoints REST o impedir que PHP lea archivos de tema/plugin.
  • Solución: Revisa logs del WAF; revierte permisos a una baseline conocida; asegura que el usuario PHP pueda leer código y escribir uploads/cache donde sea necesario.

Listas de verificación / plan paso a paso (restaurar servicio, luego prevenir)

Fase 1: Restaurar servicio (prioridad: impacto usuario)

  1. Confirma el modo WSOD con curl (estado, tamaño, tiempo de respuesta).
  2. Evita caches/CDN y prueba el origen.
  3. Lee los registros del servidor web y PHP-FPM en busca de errores fatales y timeouts.
  4. Desactiva todos los plugins (WP-CLI). Vuelve a probar.
  5. Cambia a un tema por defecto. Vuelve a probar.
  6. Comprueba disco/inodos y estado de montaje (full/solo-lectura mata WordPress rápido).
  7. Verifica conectividad BD y saturación de conexiones.
  8. Revierte el último cambio (plugin/tema/versión PHP) si la causa no es obvia en 30 minutos.

Fase 2: Identificar la causa exacta (prioridad: no repetir)

  1. Captura el primer stack trace fatal (log de depuración de WordPress o error log de PHP).
  2. Reproduce en un entorno controlado con el mismo set de plugins/tema y versión de PHP.
  3. Localiza la solicitud que dispara el fallo: homepage, shortcode, cron, admin-ajax, ruta REST.
  4. Arregla el bug o reemplaza el componente; añade una prueba de regresión (aunque sea un curl sintético que verifique HTML no vacío).
  5. Decide si ajustar memoria/timeouts—solo después de entender la ruta de código.

Fase 3: Prevención (prioridad: que el futuro tú duerma)

  • Paridad en staging: misma lista de plugins, misma versión de PHP, mismas capas de caché.
  • Logs centralizados: Nginx/Apache + PHP-FPM + log de depuración de WordPress (rotados).
  • Disciplina en despliegues: reinicia PHP-FPM cuando OPcache no valida timestamps; evita “despliegues parciales”.
  • Checks de salud reales: haz hit a endpoints dinámicos y valida el tamaño del body, no solo el status code.
  • Monitorización de almacenamiento: alerta en % de disco, % de inodos y eventos de remontaje en solo lectura.

Preguntas frecuentes

1) ¿Por qué obtengo una página en blanco con HTTP 200?

Porque la petición se completa a nivel HTTP, pero PHP no produce salida—a menudo debido a un error fatal, buffering o corte del output. Los logs dicen la verdad.

2) ¿Debo activar display_errors en producción?

No. Registra los errores en su lugar. La salida pública de errores es una fuga de información y puede romper aún más las respuestas. Habilita WP_DEBUG_LOG y mantén WP_DEBUG_DISPLAY en false.

3) ¿Cuál es la forma más rápida de descartar plugins?

WP-CLI: wp plugin deactivate --all. Si no tienes WP-CLI, renombra wp-content/plugins a otra cosa y vuelve a probar.

4) ¿Un tema puede realmente causar WSOD?

Sí. Los temas ejecutan PHP. Un fatal en functions.php o una parte de plantilla puede dejar el sitio en blanco tan eficazmente como un plugin.

5) ¿Por qué WSOD ocurre solo a veces?

WSOD intermitente suele significar contención de recursos: workers PHP-FPM agotados, conexiones BD al máximo, latencia de cache o bloqueos de almacenamiento. Busca timeouts y métricas de saturación, no solo fatales.

6) ¿Y si wp-admin también está en blanco?

Eso apunta a un problema global: un must-use plugin, un desajuste de archivos core, crash de extensión PHP, fallo de base de datos o almacenamiento/permisos. Empieza con los logs, luego desactiva plugins/temas desde el sistema de archivos o la base de datos.

7) ¿Cómo cambio el tema si no tengo WP-CLI?

Edita las opciones de la base de datos template y stylesheet a un tema por defecto. O instala WP-CLI; es más seguro que SQL manual cuando estás estresado.

8) ¿OPcache podría causar WSOD?

Indirectamente, sí: el bytecode obsoleto puede seguir ejecutando código roto después de “arreglar” archivos. Si despliegas sin reiniciar PHP-FPM y OPcache no valida timestamps, estás jugando a la ruleta.

9) ¿Aumentar el límite de memoria es una solución válida?

Como mitigación temporal, a veces. Como solución final, rara vez. Si una petición necesita de repente el doble de memoria, algo cambió: una actualización de plugin, una consulta, un bucle infinito o crecimiento de payload.

10) ¿Cómo evito que el CDN cachee la página en blanco?

Purge las rutas afectadas y asegura que tu origen no devuelva 200 vacío durante fallos. Configura reglas de cache en edge que respeten estados de error y considera una comprobación sintética que valide HTML no vacío.

Próximos pasos (prácticos, no inspiracionales)

Haz esto la próxima vez que WSOD aparezca:

  1. Ejecuta curl y confirma estado, tamaño y si estás mirando cache de borde u origen.
  2. Lee Nginx/Apache error logs y PHP-FPM logs antes de cambiar cualquier otra cosa.
  3. Desactiva plugins, cambia tema y vuelve a probar—aislar rápido vence a razonar lento.
  4. Comprueba disco/inodos y estado de montaje. Los fallos de almacenamiento consumen horas porque parecen “a nivel de aplicación”.
  5. Una vez restaurado, escribe la única causa raíz, el cambio que lo disparó y la salvaguarda que vas a añadir.

Si solo añades una guardia: haz que tu check de salud obtenga una página dinámica de WordPress y falle si el body está vacío. WSOD ama esconderse detrás de “200 OK.” No se lo permitas.

← Anterior
Lecturas solo de metadatos en ZFS: cómo el vdev especial cambia las reglas
Siguiente →
DLSS explicado: el mayor truco de FPS de la década

Deja un comentario