Actualizaste WordPress (o un plugin, o PHP), recargaste la página y tu sitio se convirtió en una escena del crimen. Pantalla en blanco. Errores 500. “Brevemente no disponible por mantenimiento programado.” Carrito de compra muerto. El director ejecutivo te escribe como si hubieras desenchufado internet personalmente.
Esto es un playbook de recuperación en producción escrito para quienes administran sistemas reales: quieres diagnóstico rápido, reversión segura y el mínimo de heroísmos. No necesitas folklore. Necesitas un cronómetro, registros y un plan.
La regla de los 30 minutos: el triage vence a la perfección
En los primeros 30 minutos, tu único trabajo es restaurar el servicio de forma segura, no resolver WordPress como concepto filosófico. Eso significa hacer cambios rápidos y reversibles, tomar notas y resistir la tentación de “ajustar una cosa más”.
Piénsalo como un SRE: elige la intervención más pequeña que restaure la disponibilidad preservando la evidencia. Tu yo futuro te lo agradecerá cuando hagas la revisión postincidente y no tengas que adivinar cuál de las ocho “pequeñas ediciones” lo arregló.
Prioridades operativas (en orden)
- Detén la hemorragia: restaura una versión operativa (incluso si está degradada, por ejemplo desactivando un plugin).
- Confirma qué está roto: errores HTTP, fatales de PHP, conectividad con BD, errores de permisos, agotamiento de recursos.
- Estabiliza: elimina el desencadenante, verifica cachés, confirma trabajos en segundo plano.
- Sólo entonces persigue la causa raíz y planifica una solución limpia hacia adelante.
Una cita que vale la pena tener en un post-it: Paráfrasis de la idea: “La esperanza no es una estrategia.”
— comúnmente atribuida en círculos de ingeniería a practicantes como Gene Kranz; el punto sigue siendo válido.
Broma #1: Las actualizaciones son como paracaídas: si las pruebas solo después de saltar, vas a aprender mucho, muy rápido.
Playbook de diagnóstico rápido (primeras/segundas/terceras comprobaciones)
Este es el camino más rápido al cuello de botella. No improvises. Sigue la secuencia para no perder 20 minutos en la capa equivocada.
Primero: ¿cuál es la falla visible para el usuario?
- 503 “modo mantenimiento” o mensaje sobre “Brevemente no disponible”: probablemente el archivo
.maintenanceestá atascado o la actualización se abortó. - 500 / 502 / 504: problema entre servidor web ↔ PHP-FPM, fatal de PHP, timeout del upstream, agotamiento de recursos.
- “Error establishing a database connection”: credenciales de BD, BD caída, socket/host incorrecto, demasiadas conexiones.
- Pantalla en blanco: fatal de PHP con display off, o fatal en tema/plugin temprano en el bootstrap.
- El sitio carga pero va lento: invalidación de caché, opciones autoloaded excesivas, desajuste de caché de objetos, consultas DB lentas.
Segundo: Revisa los registros donde vive la verdad
- Registro de errores del servidor web (Nginx/Apache).
- Registro de PHP-FPM (o journal de systemd para php-fpm).
- Registro de depuración de WordPress (si está habilitado).
- Registros/estado de la base de datos (si hay síntomas de BD).
Tercero: Haz la reversión segura más pequeña
- Desactiva los plugin(s) más recientes o cambia el tema.
- Revertir el despliegue de código (symlink o deploy git) si lo tienes.
- Restaurar desde backup solo si la reversión no es posible o cambió el esquema de BD y no puedes reconciliarlo.
Atajo de decisión
Si no puedes identificar la capa fallida en 5 minutos, deja de navegar y empieza a capturar:
- Códigos de estado HTTP actuales para
/y/wp-admin/. - Últimas 50 líneas de registros de error de web + PHP.
- Cambios de archivo recientes (
mtime) enwp-content.
Qué suele significar “se rompió después de una actualización”
1) Actualización del core de WordPress aplicada parcialmente
Una actualización del core que se interrumpe (permisos, disco lleno, timeout) puede dejar versiones mixtas. Síntomas: errores fatales en archivos del core, archivos faltantes, comportamiento aleatorio y el clásico bloqueo en “modo mantenimiento”.
2) La actualización de un plugin introdujo un error fatal
Lo más común. Un plugin asume una versión de PHP, una función o la presencia de otro plugin. O tiene un typo que no pasó por el CI de alguien. Síntomas: pantalla en blanco, 500s, errores fatales que referencian una ruta de plugin.
3) Actualización de tema o código personalizado incompatible
Mismo relato que con los plugins, más el añadido de funciones personalizadas en functions.php escritas en 2017 y probadas por última vez en PHP 7.4.
4) Cambió la versión de PHP debajo de ti
Actualizaciones del SO, upgrades del panel o un “cambio menor” de imagen pueden subir la versión de PHP. Síntomas: fatales como “Call to undefined function”, warnings deprecados que se vuelven fatales (según configuración), o extensiones faltantes (mysqli, intl, imagick).
5) Desajuste de caché / caché de objetos
Plugins de object cache para Redis/Memcached pueden fallar cuando cambia el backend, cambia el plugin o varía el formato de serialización. Síntomas: el admin funciona pero el frontend falla, bucles de redirección extraños, errores intermitentes que desaparecen al limpiar la caché.
6) Migraciones de base de datos y deriva de esquema
Algunos plugins ejecutan migraciones al actualizar. Si fallan a la mitad, obtienes pantallas de administración rotas, tablas faltantes o consultas de larga duración que golpean el sitio.
7) La mentira “todo está bien”: en realidad es almacenamiento o permisos
Las actualizaciones escriben archivos. Las escrituras necesitan espacio, propietario/grupo correctos y opciones de montaje sensatas. Si el disco está lleno o los permisos son incorrectos, tienes actualizaciones parciales, fallos repetidos y un sitio que parece poseído.
Tareas prácticas de recuperación (comandos, salidas, decisiones)
Estas tareas están diseñadas para ejecutarse en orden. Cada una incluye: comando, salida realista, lo que significa y la decisión que tomas.
Supuestos: host Linux, Nginx o Apache, PHP-FPM, WordPress en /var/www/wordpress. Ajusta rutas, pero no improvises. Confirma primero.
Tarea 1: Confirma lo que ve el mundo (estado HTTP, cabeceras, tiempos)
cr0x@server:~$ curl -sS -D- -o /dev/null https://example.com/
HTTP/2 502
date: Fri, 27 Dec 2025 18:41:12 GMT
content-type: text/html
server: nginx
Significado: Nginx es accesible, pero el upstream (PHP-FPM) falla o hace timeout.
Decisión: Deja de tocar archivos de WordPress. Ve al registro de errores de Nginx y luego al estado/registros de PHP-FPM.
Tarea 2: Identifica la pila web (Nginx vs Apache) y estado de servicios
cr0x@server:~$ systemctl status nginx php8.2-fpm --no-pager
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: active (running) since Fri 2025-12-27 18:02:19 UTC; 38min ago
● php8.2-fpm.service - The PHP 8.2 FastCGI Process Manager
Loaded: loaded (/lib/systemd/system/php8.2-fpm.service; enabled; preset: enabled)
Active: failed (Result: exit-code) since Fri 2025-12-27 18:39:58 UTC; 1min 14s ago
Significado: PHP-FPM está caído; WordPress ni siquiera tiene oportunidad de ejecutarse.
Decisión: Inspecciona los logs del journal de PHP-FPM; probablemente sea un cambio de configuración, fallo de una extensión o restricción de recursos.
Tarea 3: Lee la razón de la falla de PHP-FPM (journal)
cr0x@server:~$ sudo journalctl -u php8.2-fpm -n 80 --no-pager
Dec 27 18:39:58 server php-fpm8.2[21983]: ERROR: failed to open configuration file '/etc/php/8.2/fpm/php-fpm.conf': Permission denied (13)
Dec 27 18:39:58 server systemd[1]: php8.2-fpm.service: Main process exited, code=exited, status=78/CONFIG
Dec 27 18:39:58 server systemd[1]: php8.2-fpm.service: Failed with result 'exit-code'.
Significado: Esto no es WordPress. Es un problema de permisos a nivel OS en un archivo de configuración. Normalmente causado por una regla de hardening mal aplicada, propietario incorrecto o modo de archivo roto durante una actualización de paquete.
Decisión: Arregla permisos en ese archivo (o restaura desde el paquete), luego reinicia PHP-FPM. No toques plugins todavía.
Tarea 4: Valida permisos del archivo de configuración y restaura modos sensatos
cr0x@server:~$ sudo ls -l /etc/php/8.2/fpm/php-fpm.conf
---------- 1 root root 4217 Dec 27 18:38 /etc/php/8.2/fpm/php-fpm.conf
Significado: El modo es 000; nadie puede leerlo, incluyendo PHP-FPM al arrancar (según la política de la distro). Eso está roto.
Decisión: Restaura a un típico 644, reinicia, vuelve a probar HTTP. Si eso trae el sitio de vuelta, debes investigar por qué cambió durante la actualización.
cr0x@server:~$ sudo chmod 644 /etc/php/8.2/fpm/php-fpm.conf
cr0x@server:~$ sudo systemctl restart php8.2-fpm
cr0x@server:~$ 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; preset: enabled)
Active: active (running) since Fri 2025-12-27 18:42:10 UTC; 3s ago
Significado: PHP-FPM está sano de nuevo.
Decisión: Vuelve a ejecutar curl. Si sigue fallando, ahora pivotas a los registros a nivel de aplicación.
Tarea 5: Revisa el registro de errores de Nginx por pistas del upstream
cr0x@server:~$ sudo tail -n 40 /var/log/nginx/error.log
2025/12/27 18:41:11 [error] 1132#1132: *889 upstream sent too big header while reading response header from upstream, client: 203.0.113.21, server: example.com, request: "GET / HTTP/2.0", upstream: "fastcgi://unix:/run/php/php8.2-fpm.sock:", host: "example.com"
Significado: Este es un modo de falla real tras actualizaciones: un plugin/tema cambia cookies o cabeceras, y la respuesta upstream excede los límites de buffer de Nginx.
Decisión: Si este es el bloqueo actual, ajusta los buffers fastcgi de Nginx como mitigación, pero también busca el plugin que está generando cookies/cabeceras enormes.
Tarea 6: Captura el fatal real de PHP (habilita logging sin mostrar a los usuarios)
No actives display_errors en producción. Registra el error.
cr0x@server:~$ sudo grep -n "WP_DEBUG\|WP_DEBUG_LOG\|WP_DEBUG_DISPLAY" /var/www/wordpress/wp-config.php
88:define('WP_DEBUG', false);
Significado: El debug está apagado; puedes estar ciego.
Decisión: Habilita temporalmente WP_DEBUG_LOG y mantén display off. Luego reproduce una vez, lee el log y revierte después.
cr0x@server:~$ sudo sed -i "s/define('WP_DEBUG', false);/define('WP_DEBUG', true);\ndefine('WP_DEBUG_LOG', true);\ndefine('WP_DEBUG_DISPLAY', false);/g" /var/www/wordpress/wp-config.php
cr0x@server:~$ sudo -u www-data php -v
PHP 8.2.14 (cli) (built: Dec 5 2025 09:01:22) (NTS)
Significado: Habilitaste el logging de debug. El CLI de PHP está presente; útil para ejecutar WP-CLI o pruebas rápidas.
Decisión: Toca el endpoint que falla una vez, luego inspecciona wp-content/debug.log.
Tarea 7: Lee el log de depuración de WordPress y localiza al culpable
cr0x@server:~$ sudo tail -n 30 /var/www/wordpress/wp-content/debug.log
[27-Dec-2025 18:43:02 UTC] PHP Fatal error: Uncaught Error: Call to undefined function mb_strlen() in /var/www/wordpress/wp-content/plugins/newsletter-pro/includes/parser.php:117
Stack trace:
#0 /var/www/wordpress/wp-settings.php(453): include_once()
#1 /var/www/wordpress/wp-config.php(90): require_once('...')
#2 /var/www/wordpress/wp-load.php(50): require_once('...')
#3 /var/www/wordpress/wp-blog-header.php(13): require_once('...')
#4 /var/www/wordpress/index.php(17): require('...')
#5 {main}
thrown in /var/www/wordpress/wp-content/plugins/newsletter-pro/includes/parser.php on line 117
Significado: El código del plugin llamó a mb_strlen(), pero la extensión PHP mbstring no está cargada. Esto ocurre comúnmente tras una actualización de PHP o cambio de paquetes.
Decisión: Restaura el servicio rápido desactivando el plugin o instalando la extensión faltante. Elige el cambio de menor riesgo para tu entorno.
Tarea 8: Confirma la extensión PHP faltante
cr0x@server:~$ php -m | grep -i mbstring || echo "mbstring not loaded"
mbstring not loaded
Significado: La extensión falta.
Decisión: Instala el paquete php-mbstring para tu distro/versión de PHP; luego reinicia PHP-FPM. Si no puedes instalar rápidamente (control de cambios), desactiva el plugin primero.
Tarea 9: Desactivar un plugin sin wp-admin (renombrar directorio)
cr0x@server:~$ cd /var/www/wordpress/wp-content/plugins
cr0x@server:~$ sudo mv newsletter-pro newsletter-pro.disabled
cr0x@server:~$ ls -1 | head
akismet
hello.php
newsletter-pro.disabled
woocommerce
Significado: WordPress no podrá cargar un directorio de plugin renombrado; en la próxima carga se desactivará efectivamente.
Decisión: Vuelve a probar el sitio. Si regresa, confirmaste al culpable y ganaste tiempo para instalar mbstring y reactivar con seguridad.
Tarea 10: Arreglar rápidamente “atascado en modo mantenimiento”
cr0x@server:~$ sudo ls -la /var/www/wordpress/.maintenance
-rw-r--r-- 1 www-data www-data 52 Dec 27 18:37 /var/www/wordpress/.maintenance
Significado: WordPress dejó un archivo de bloqueo de mantenimiento, usualmente por una actualización interrumpida.
Decisión: Elimínalo y prueba de nuevo. Si vuelve a aparecer, las actualizaciones siguen fallando (permisos, disco o sistema de ficheros).
cr0x@server:~$ sudo rm -f /var/www/wordpress/.maintenance
cr0x@server:~$ curl -sS -o /dev/null -w "%{http_code}\n" https://example.com/
200
Tarea 11: Verifica espacio en disco y presión de inodos (las actualizaciones necesitan escritura)
cr0x@server:~$ df -h /var/www /tmp
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 39G 260M 100% /
tmpfs 1.9G 12M 1.9G 1% /tmp
Significado: El filesystem root está lleno. Las actualizaciones fallarán de maneras creativas, incluyendo escrituras parciales y la imposibilidad de crear archivos temporales.
Decisión: Libera espacio inmediatamente (logs, versiones antiguas, cachés). Luego vuelve a ejecutar la actualización en una ventana controlada. También revisa inodos si tienes muchos archivos pequeños.
cr0x@server:~$ df -i /
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/vda1 262144 261900 244 100% /
Significado: Agotamiento de inodos. Falla clásica de WordPress con demasiados archivos cacheados o backups almacenados localmente.
Decisión: Borra directorios de alta rotación (cache, tmp), mueve backups fuera del host y establece políticas de retención.
Tarea 12: Revisa propietario y permisos en wp-content
cr0x@server:~$ sudo find /var/www/wordpress/wp-content -maxdepth 1 -type d -printf "%M %u:%g %p\n"
drwxr-xr-x root root /var/www/wordpress/wp-content
drwxr-xr-x root root /var/www/wordpress/wp-content/plugins
drwxr-xr-x root root /var/www/wordpress/wp-content/themes
drwxrwx--- www-data www-data /var/www/wordpress/wp-content/uploads
Significado: Si plugins/temas son propiedad de root y no escribibles por el usuario web, las actualizaciones desde el panel pueden fallar a mitad. Eso no es inherentemente incorrecto (algunas organizaciones desean código inmutable), pero entonces debes desplegar actualizaciones por otro medio.
Decisión: Elige un modelo: o código inmutable (pipeline de despliegue; desactivar ediciones desde el panel), o permitir que WordPress escriba (menos seguro). No te quedes en el punto intermedio maldito donde las actualizaciones funcionan a medias.
Tarea 13: Usa WP-CLI para listar y desactivar plugins (limpio y auditable)
cr0x@server:~$ cd /var/www/wordpress
cr0x@server:~$ sudo -u www-data wp plugin list --status=active
+-------------------+----------+--------+---------+
| name | status | update | version |
+-------------------+----------+--------+---------+
| woocommerce | active | none | 9.2.1 |
| wordpress-seo | active | none | 23.1 |
| newsletter-pro | active | none | 4.0.0 |
+-------------------+----------+--------+---------+
Significado: Puedes administrar plugins sin wp-admin. Esta es la forma adulta de hacer cambios de emergencia.
Decisión: Desactiva los plugin(s) sospechosos primero; prueba; luego itera.
cr0x@server:~$ sudo -u www-data wp plugin deactivate newsletter-pro
Plugin 'newsletter-pro' deactivated.
Tarea 14: Cambia a un tema por defecto sin wp-admin
cr0x@server:~$ sudo -u www-data wp theme list
+----------------+----------+--------+---------+
| name | status | update | version |
+----------------+----------+--------+---------+
| twentytwentyfour | inactive | none | 1.2 |
| custom-theme | active | none | 3.8.7 |
+----------------+----------+--------+---------+
Significado: Si la actualización del tema rompió el renderizado, cambiar de tema puede restaurar el frontend rápidamente (el admin suele permanecer accesible).
Decisión: Activa temporalmente un tema por defecto y luego arregla el código del tema fuera de línea.
cr0x@server:~$ sudo -u www-data wp theme activate twentytwentyfour
Success: Switched to 'Twenty Twenty-Four' theme.
Tarea 15: Diagnostica conectividad BD vs configuración de la app
cr0x@server:~$ sudo -u www-data php -r "require '/var/www/wordpress/wp-config.php'; echo DB_HOST, PHP_EOL;"
localhost
Significado: Confirma lo que WordPress cree que es el host de BD (útil cuando intervienen variables de entorno o includes).
Decisión: Si aparecen errores de BD, prueba la conectividad TCP/socket y las credenciales directamente.
cr0x@server:~$ mysql -h localhost -u wpuser -p -e "SELECT 1;"
Enter password:
1
1
Significado: La BD es accesible y las credenciales funcionan desde este host.
Decisión: Si WordPress sigue diciendo que no puede conectar, sospecha socket equivocado, DB_HOST errado (p. ej. necesita 127.0.0.1), o PHP sin la extensión mysqli.
Tarea 16: Comprueba extensiones PHP para MySQL
cr0x@server:~$ php -m | egrep -i "mysqli|pdo_mysql" || echo "no mysql extensions loaded"
mysqli
pdo_mysql
Significado: PHP puede hablar con MySQL.
Decisión: Si la BD sigue fallando, revisa conexiones máximas y salud de la BD.
Tarea 17: Revisa carga de BD y saturación de conexiones
cr0x@server:~$ mysql -uroot -p -e "SHOW STATUS LIKE 'Threads_connected'; SHOW VARIABLES LIKE 'max_connections';"
Enter password:
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Threads_connected | 198 |
+-------------------+-------+
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 200 |
+-----------------+-------+
Significado: Estás al límite. Una actualización que aumente consultas (o rompa caché) puede llevarte a “demasiadas conexiones”, que WordPress reporta como fallo de conexión a BD.
Decisión: A corto plazo: reinicia PHP-FPM para soltar conexiones inactivas, escala la BD o reduce concurrencia. A mediano plazo: arregla la explosión de consultas (a menudo un plugin) y habilita caché de objetos correctamente.
Tarea 18: Confirma qué cambió recientemente (scan mtime)
cr0x@server:~$ sudo find /var/www/wordpress/wp-content -type f -mtime -1 -printf "%TY-%Tm-%Td %TH:%TM %p\n" | tail -n 10
2025-12-27 18:36 /var/www/wordpress/wp-content/plugins/newsletter-pro/includes/parser.php
2025-12-27 18:36 /var/www/wordpress/wp-content/plugins/newsletter-pro/newsletter-pro.php
2025-12-27 18:35 /var/www/wordpress/wp-content/themes/custom-theme/functions.php
Significado: Esto reduce la lista de sospechosos a lo que realmente cambió.
Decisión: Prioriza desactivar/revertir los componentes modificados más recientemente.
Broma #2: Nada motiva la higiene de logs como un error 500 y un panel que no carga.
Tres microhistorias corporativas desde el campo
Microhistoria 1: El incidente causado por una suposición equivocada
Ejecutaban un sitio de marketing WordPress en una VM ordenada. El equipo “sabía” que era simple: Nginx + PHP-FPM + MariaDB. La actualización en cuestión era “solo un parche de seguridad” para un plugin popular de formularios.
El parche se aplicó y en minutos el sitio empezó a servir 502 intermitentes. Alguien asumió que era un bug del plugin y empezó a revertir versiones del plugin. Otra persona comenzó a aumentar workers de PHP-FPM. El tráfico seguía fallando por oleadas.
La suposición equivocada: “Si es un 502, es PHP.” No lo era. La actualización del plugin aumentó el número de llamadas HTTP salientes (chequeos de spam, validación API) y la VM tenía una política de firewall saliente que descartaba silenciosamente esas conexiones en lugar de rechazarlas rápido. Los workers de PHP se quedaron esperando timeouts de red. Nginx hizo timeout del upstream. 502.
La solución fue aburrida: permitir salidas a un pequeño conjunto de endpoints API, poner timeouts sensatos en cURL y limitar la duración de solicitudes en PHP-FPM. El plugin no estaba “roto”. El sistema fue configurado para fallar lentamente, que es la peor clase de fallo en producción.
La acción de postmortem que importó: cuando ves 502s, verifica si PHP está muriendo rápido (fatales) o muriendo lento (timeouts). Tu siguiente paso cambia completamente.
Microhistoria 2: La optimización que salió mal
Otra organización tenía un stack ocupado con WordPress + WooCommerce. Alguien decidió “optimizar” activando cache de página agresiva y cacheando usuarios autenticados “porque parecía bien en staging”. También encendieron Redis como caché de objetos con la configuración por defecto. Era viernes. Por supuesto que era viernes.
Luego actualizaron WooCommerce. La actualización añadió algunas cookies y cambió la lógica de sesiones. De pronto los clientes veían los carritos de otros. No siempre. Lo suficiente para ser aterrador. Los tickets de soporte explotaron.
El fallo fue sutil: su capa de caché no variaba correctamente según cookies y estado de autenticación después de la actualización. La lógica anterior casualmente funcionaba con el comportamiento antiguo de cookies; la nueva versión expuso la suposición incorrecta. Técnicamente la caché hizo lo que se le dijo. Operativamente, cometió un pequeño crimen.
La recuperación fue un bypass rápido de caché para rutas de usuarios autenticados y relacionadas con el carrito, luego una reintroducción cuidadosa de la caché con reglas de vary correctas. La lección profunda: la caché no es un interruptor, es un producto. Y “parece bien” no es un plan de pruebas.
Microhistoria 3: La práctica aburrida pero correcta que salvó el día
Una tercera empresa ejecutaba WordPress en un par de servidores de aplicación detrás de un balanceador, con la base de datos en almacenamiento gestionado. Hacían actualizaciones semanales de plugins. Nada extravagante. Pero tenían dos hábitos: (1) releases de apps inmutables (directorios symlinkados), y (2) backup nocturno de BD con pruebas de restauración verificadas.
Una actualización introdujo un error fatal en un plugin premium. De inmediato tumbó el frontend. El ingeniero on-call no debuggeó en vivo. Hizo lo aburrido: apuntó el symlink a la release anterior, limpió la caché de opcode y confirmó 200s. Tiempo total de caída: minutos.
Luego investigaron. La actualización del plugin requería una extensión PHP más reciente. En dev estaba instalada por defecto. En prod no. El fatal era legítimo, pero ya no era urgente porque el servicio se había restaurado.
Avanzaron más tarde ese mismo día tras instalar la extensión y fijar la versión del plugin hasta que el proveedor aclarara requisitos. La práctica aburrida—releases que puedes revertir con un comando—no se sintió glamorosa. Se sintió como dinero.
Errores comunes: síntoma → causa raíz → solución
1) “Brevemente no disponible por mantenimiento” para siempre
Síntoma: Frontend y admin muestran el mensaje de mantenimiento horas después de una actualización.
Causa raíz: Archivo .maintenance dejado tras una actualización interrumpida (timeout, permisos, disco lleno).
Solución: Elimina /var/www/wordpress/.maintenance. Luego revisa inmediatamente espacio en disco y permisos de archivos, o volverá a ocurrir.
2) 502 Bad Gateway tras actualizar
Síntoma: Nginx devuelve 502; intermitente o constante.
Causa raíz: PHP-FPM caído, workers de PHP bloqueados, mismatch de socket o problemas de buffer en el upstream.
Solución: Revisa systemctl status php*-fpm, lee el journal, luego revisa el log de Nginx por “connect() failed”, “upstream timed out” o “too big header”. Arregla el mensaje real, no la sensación.
3) Pantalla en blanco de la muerte (WSOD)
Síntoma: Página en blanco, quizá 200 OK, sin contenido.
Causa raíz: Fatal de PHP con display desactivado; a menudo un plugin/tema.
Solución: Habilita temporalmente WP_DEBUG_LOG e inspecciona wp-content/debug.log. Desactiva el plugin o tema que falla. Revierte debug después.
4) “Error establishing a database connection”
Síntoma: WordPress muestra error de conexión a BD inmediatamente.
Causa raíz: BD caída, credenciales incorrectas, conexiones agotadas, problemas DNS o falta de extensión MySQL en PHP tras una actualización.
Solución: Prueba el login a la BD desde el host, verifica DB_HOST, contempla Threads_connected vs max_connections, asegúrate de que mysqli/pdo_mysql esté cargado.
5) El admin funciona, el frontend falla (o viceversa)
Síntoma: /wp-admin/ carga pero la página principal da 500, o la página principal funciona pero el admin está roto.
Causa raíz: Fallo sólo en el tema, problemas de caché o un plugin enganchado sólo en rutas de frontend.
Solución: Cambia a un tema por defecto vía WP-CLI y desactiva temporalmente plugins de caché/caché de objetos. Confirma con logs.
6) Redirecciones aleatorias / bucles de inicio de sesión tras actualizar
Síntoma: No puedes mantener la sesión, redirecciones entre http/https o bucles alrededor de wp-login.php.
Causa raíz: Opciones siteurl/home mal configuradas, cabeceras SSL del proxy cambiadas o caché que varía incorrectamente según cookies.
Solución: Confirma cabeceras del proxy, asegura que WordPress detecte HTTPS correctamente, comprueba valores en BD de las URLs del sitio, purga cachés y arregla reglas de vary.
7) La UI de actualización dice éxito, pero el código está medio actualizado
Síntoma: Los números de versión cambian en el panel, pero faltan archivos o son antiguos.
Causa raíz: Permisos mezclados (algunos directorios escribibles y otros no), o disco lleno a mitad de extracción.
Solución: Deja de hacer actualizaciones desde el panel a menos que el servidor esté configurado para ello. Usa un método de despliegue atómico o arregla la propiedad consistentemente y monitoriza disco/inodos.
Listas de verificación / plan paso a paso
El plan de recuperación de 30 minutos (haz esto, en este orden)
- Inicia una línea de tiempo: anota la hora, qué se actualizó y el síntoma actual.
- Confirma códigos de estado:
curla la página principal y a/wp-admin/. - Revisa la salud de servicios: estado de Nginx/Apache y PHP-FPM.
- Lee los registros: log de errores web, journal de PHP-FPM, log de depuración de WordPress (habilita logging si hace falta).
- Busca los bloqueos obvios:
.maintenance, disco lleno, inodos agotados, permisos. - Revierte la unidad más pequeña: desactiva el plugin más nuevo o cambia el tema.
- Verifica la recuperación: 200s, login funciona, camino crítico de checkout funciona.
- Estabiliza la caché: purga cache de página, resetea cache de objetos si está en el camino.
- Captura evidencia: guarda el stack trace fatal y diffs de configuración relevantes.
- Revierte cambios temporales de debug: apaga
WP_DEBUGy elimina logs sensibles si es necesario.
Cuándo restaurar desde backup (y cuándo no)
- Restaura desde backup si: se ejecutaron migraciones de esquema de BD y no puedes deshacerlas; faltan archivos en core; tienes evidencia de corrupción; no tienes mecanismo limpio de rollback.
- No restaures desde backup si: es solo un fatal de un plugin que puedes desactivar; te falta una extensión PHP; un servicio está caído; el disco está lleno. Los backups son para pérdida de datos, no para troubleshooting básico.
Redes de seguridad para arreglos en producción
- Prefiere desactivar un plugin antes que “editarlo en vivo”.
- Haz un cambio a la vez. Si no puedes explicar lo que cambiaste, no puedes revertirlo.
- Si debes cambiar configuración, captura un diff primero.
- Cualquier cosa que implique escrituras a la BD debe tratarse como riesgosa durante la respuesta a incidentes. Primero investigaciones en modo lectura.
Hechos interesantes y contexto histórico (porque ayuda)
- WordPress empezó en 2003 como un fork de b2/cafelog, y su ecosistema de plugins creció más rápido que la higiene de dependencias de la mayoría.
- Las actualizaciones automáticas en segundo plano para releases menores del core se hicieron estándar años después, lo que redujo ventanas de vulnerabilidad conocidas pero aumentó incidentes por “cambios sorpresa” en entornos con poca observabilidad.
- La “pantalla en blanco de la muerte” no es única de WordPress; es lo que obtienes cuando los fatales de PHP se encuentran con configuraciones de producción que suprimen la salida.
- Los saltos de versión de PHP importan: cambios como comportamiento de tipado más estricto y funciones deprecadas han roto repetidamente temas y plugins antiguos, especialmente los a medida.
- El caching de objetos en WordPress es opcional por diseño; cuando se habilita puede reducir dramáticamente la carga de BD—o amplificar rarezas si la serialización, los TTLs o las claves de caché están mal manejados.
- Las escrituras en el sistema de ficheros forman parte del mecanismo de actualización: las actualizaciones de WordPress típicamente descargan zips, los extraen e intercambian archivos. Por eso los fallos de disco/inodos aparecen como “problemas de actualización”.
- Las actualizaciones de plugins pueden incluir migraciones de base de datos, y esas migraciones a menudo se ejecutan bajo timeouts de solicitud web—una restricción arquitectónica que puede crear estados medio aplicados.
- El archivo de bloqueo .maintenance es un mecanismo simple: WordPress lo crea durante upgrades y lo elimina al terminar. Si te caes a mitad de upgrade, se queda. Simple, efectivo, ocasionalmente molesto.
Preguntas frecuentes
1) No puedo acceder a wp-admin. ¿Cuál es la forma más rápida de desactivar plugins?
Renombra el directorio del plugin bajo wp-content/plugins o usa WP-CLI: wp plugin deactivate plugin-name. Renombrar funciona incluso cuando PHP está medio roto.
2) ¿Es seguro habilitar WP_DEBUG en producción durante un incidente?
Sí, si mantienes WP_DEBUG_DISPLAY en false y usas WP_DEBUG_LOG en true temporalmente. Apágalo después de capturar el error.
3) ¿Por qué veo 200 OK pero una página en blanco?
PHP puede fallar antes de generar salida, y tu servidor aún puede devolver 200 con cuerpo vacío. Por eso los registros importan más que el comportamiento del navegador.
4) ¿Debo revertir el core de WordPress primero o los plugins?
Primero plugins/temas. Los rollbacks de core son más riesgosos si ya se ejecutó una migración de base de datos. La mayoría de las roturas tras “una actualización” son por plugin/tema o por cambios en PHP/entorno.
5) ¿Qué pasa si la actualización cambió el esquema de la base de datos?
Trátalo con cuidado. Desactiva el plugin que disparó la migración, evalúa qué tablas/opciones cambiaron y prefiere restaurar un backup de BD probado si no puedes revertir con seguridad.
6) Lo arreglé renombrando la carpeta del plugin. ¿Cómo lo vuelvo a habilitar de forma segura?
No solo lo renombres y esperes. Primero arregla la causa subyacente (extensión PHP faltante, mismatch de versión de PHP). Luego reactiva en forma controlada: en una ventana de poco tráfico, con logs abiertos y rollback rápido listo.
7) ¿Por qué una actualización del SO rompió WordPress si no toqué WordPress?
Porque WordPress corre sobre PHP, servidores web y extensiones. Si PHP se actualizó, pueden faltar extensiones, cambiar los ini por defecto y variar el comportamiento de OPcache.
8) ¿Cuál es el monitoreo mínimo que hubiera facilitado esto?
Checks de estado HTTP en la página principal y en /wp-admin/, alertas de tasa de errores, salud de PHP-FPM (proceso arriba, longitud de cola), umbrales de disco/inodos y logs de errores centralizados.
9) ¿Puede la caché causar “todo roto” después de una actualización?
Absolutamente. Redirecciones cacheadas, cabeceras sobredimensionadas y reglas de vary incorrectas pueden hacer que una app funcional parezca rota. Siempre prueba con bypass de caché y purga tras una actualización mayor.
10) ¿Cuándo debo sospechar del almacenamiento?
Si las actualizaciones fallan repetidamente, ves cambios parciales de archivos, recibes errores de permisos o el disco/inodos están casi llenos. Los fallos de almacenamiento a menudo se hacen pasar por “bugs de WordPress”.
Pasos siguientes después de volver a estar en línea
Una vez que el sitio esté estable, no vuelvas a la normalidad de forma apresurada. Usa la calma para eliminar las condiciones que hicieron posible el incidente.
- Anota el disparador raíz: qué actualización, qué componente, qué mensaje en logs, qué parche aplicaste.
- Pon las actualizaciones en rieles: adopta despliegues inmutables (recomendado) o haz consistentes los permisos del filesystem para actualizaciones desde el panel (menos recomendado).
- Añade un mecanismo de rollback: releases versionadas, snapshots o al menos un procedimiento de restauración probado.
- Audita extensiones y versiones de PHP: define explícitamente lo que debe tener producción y haz que se cumpla.
- Prueba actualizaciones en un entorno parecido a producción: misma versión de PHP, mismo caching, mismas cabeceras de proxy, mismo set de plugins.
- Establece umbrales para disco e inodos: las fallas por disco lleno en actualizaciones son embarazosas porque son previsibles.
El objetivo no es “nunca romper”. El objetivo es romper de una manera que sea rápida de diagnosticar, rápida de revertir y difícil de repetir.