El editor Gutenberg de WordPress no carga: lista práctica de depuración

¿Te fue útil?

El editor Gutenberg “se carga” como llega un ascensor defectuoso: las puertas nunca se abren, el spinner sigue girando y todo el mundo empieza a culpar a la red como si tuviera una deuda.

Esta guía es para cuando el editor de bloques no carga, se queda atascado en “Actualizando…”, muestra un área de contenido en blanco o lanza “El editor ha encontrado un error inesperado.” Lo diagnosticaremos como un SRE: aislar variables, comprobar hipótesis y cambiar una cosa a la vez—porque producción no se preocupa por tu intuición.

Guion de diagnóstico rápido

Si quieres la vía más rápida al cuello de botella, deja de adivinar y ejecuta esto en orden. El objetivo no es “probar cosas”. El objetivo es identificar qué capa te está engañando.

1) Revisa primero la consola del navegador (los errores JS lo deciden todo)

  • Abre la página del editor: /wp-admin/post-new.php o /wp-admin/post.php?post=ID&action=edit.
  • DevTools → Consola: busca errores en rojo y peticiones de red fallidas.
  • DevTools → Red: filtra por wp-json, rest, block-editor, wp-admin/load-scripts.php y admin-ajax.php.

Decisión: Si ves “Failed to fetch”, “Unexpected token < in JSON” o 401/403/5xx en endpoints REST, esto no es un “problema de Gutenberg”. Es un problema de API/autenticación/WAF/caché.

2) Verifica que la REST API funcione desde el servidor (no confíes en el navegador)

Golpea /wp-json/ y un endpoint autenticado. Si tu servidor no puede alcanzarse a sí mismo (o devuelve HTML donde debería devolver JSON), Gutenberg se pondrá de mal humor.

Decisión: Si /wp-json/ está roto, arréglalo primero. Gutenberg depende de ello como el oxígeno depende de los pulmones.

3) Desactiva plugins y cambia a un tema por defecto (quirúrgico, no emocional)

Hazlo vía WP-CLI para no quedarte bloqueado por la misma interfaz que intentas arreglar.

Decisión: Si desactivar plugins lo arregla, vuelve a activarlos por lotes para identificar al culpable. Si cambiar el tema lo soluciona, busca scripts del editor, errores en enqueue o cabeceras CSP en el tema.

4) Revisa cachés y capas de seguridad (los sospechosos habituales)

  • Caché de objetos (Redis/Memcached)
  • Caché de página completa/CDN (Cloudflare, Fastly, varnish, nginx microcache)
  • Reglas WAF bloqueando wp-json o scripts de admin
  • Cabeceras CSP bloqueando scripts inline usados por WordPress

Decisión: Si el editor carga en una ventana de incógnito pero no en modo normal, busca activos cacheados, service workers o extensiones de navegador agresivas. Si el editor carga al bypassear CDN/WAF, tu configuración en el edge es la villana.

5) Confirma que PHP y el almacenamiento no estén fallando bajo carga

Gutenberg hace más peticiones que el editor clásico. Si PHP-FPM está saturado, el disco está en thrash o el opcache está fallando, el editor parecerá “atascado” pero el verdadero problema es latencia y timeouts.

Decisión: Si los logs del servidor muestran 502/504 o timeouts, arregla capacidad y latencia. Depurar WordPress con un disco moribundo es como afinar un piano durante un terremoto.

Cómo se carga realmente Gutenberg (y cómo se rompe)

Gutenberg es una aplicación JavaScript embebida dentro de wp-admin. Cuando abres el editor, WordPress devuelve una página de administración que arranca un montón de scripts (React, stores de datos, registro de bloques, UI del editor) y luego obtiene contenido y configuración mediante llamadas a la REST API.

Eso significa que los modos de fallo tienden a agruparse en cuatro categorías:

  1. Fallas de arranque: JS/CSS del editor no se carga, o se carga corrupto. Causas típicas: reescritura por caché/CDN, minificadores, contenido mixto, CSP, tipo de contenido incorrecto.
  2. Fallas de API: wp-json bloqueado, devolviendo HTML en lugar de JSON, cookies de autenticación no aceptadas, problemas de nonce, 401/403 por WAF, 5xx por PHP.
  3. Fallas en la capa de datos: rarezas en la caché de objetos, errores de base de datos, opciones autoload desbordadas, consultas lentas que caducan.
  4. Fallas del entorno: límite de memoria PHP, agotamiento de opcache, disco lleno, permisos, corrupción de archivos o un plugin de seguridad “útil” que endurece endpoints.

Cuando el editor de bloques “no carga”, a menudo no es un único error catastrófico. Es una cadena: un script falla, luego la app JS no puede obtener endpoints REST, luego muestra un spinner eternamente porque espera una promesa que nunca se resuelve. Tu trabajo es encontrar el primer eslabón roto.

Una cita que vale la pena poner en la pared, porque es molesta y cierta: La esperanza no es una estrategia. — General Gordon R. Sullivan.

Broma #1: Gutenberg es una aplicación de una sola página viviendo en un mundo de páginas múltiples. Es como poner un motor de coche de carreras en un carrito de la compra y sorprenderse cuando chirría.

Hechos interesantes y breve historia (por qué esto sigue ocurriendo)

  • Gutenberg se lanzó primero como plugin antes de fusionarse en el core de WordPress, por eso algunos sitios aún arrastran restos del plugin Gutenberg.
  • WordPress 5.0 (2018) convirtió el editor de bloques en el predeterminado, lo que de repente empujó a millones de entornos de administración a una carga de JavaScript más pesada.
  • El editor de bloques depende en gran medida de la REST API; el editor clásico podía funcionar con menos llamadas dinámicas.
  • wp-admin históricamente toleró configuraciones de caché “creativas” porque la mayoría de las páginas de administración se renderizaban en servidor. Gutenberg castiga configuraciones de caché incorrectas mucho más rápido.
  • Los plugins de seguridad empezaron a filtrar agresivamente endpoints JSON a medida que los ataques basados en REST se hicieron comunes; algunos conjuntos de reglas “resuelven” seguridad rompiendo el editor.
  • Los flujos de nonce y cookies cambiaron con el tiempo con mejoras en la seguridad administrativa, lo que significa que proxies reversos y SSO antiguos pueden quedar incompatibles.
  • Muchos plugins de optimización se diseñaron para el front-end; con gusto minifican y difieren scripts en wp-admin a menos que se configuren explícitamente para no hacerlo.
  • Los temas de bloques y la Edición Completa del Sitio aumentaron la superficie del editor (editor de sitio, partes de plantilla, estilos globales). Más endpoints. Más formas de fallar.

Primeras observaciones: clasifica la falla en 60 segundos

¿Qué ve el usuario?

  • Spinner infinito / “Cargando…” para siempre: normalmente llamada a la REST API bloqueada, o error de runtime JS temprano en el arranque.
  • Pantalla en blanco / área de contenido vacía: fallo JS fatal, bloqueo CSP, un script 404 o un fatal PHP que imprime HTML en endpoints JSON.
  • “El editor ha encontrado un error inesperado” con un botón “Copiar error”: bien; significa que Gutenberg atrapó algo. Cópialo y úsalo.
  • El editor carga pero no puede guardar/actualizar: a menudo problemas de nonce/autenticación/cookies, REST 401/403, o mod_security/WAF bloqueando POST.
  • Sucede solo para ciertos usuarios: desajuste de roles/capacidades, corrupción de usermeta, extensión del navegador o cookies CDN diferentes por grupo de usuarios.
  • Sucede solo en un post: marcado de bloque malformado, post_content enorme, HTML/shortcodes incrustados que provocan colapso del parser, o exceso de meta de revisiones.

Comprobaciones rápidas “¿es tu máquina?”

  • Prueba en ventana de incógnito/privada.
  • Prueba con otro navegador.
  • Desactiva extensiones del navegador (especialmente bloqueadores de anuncios y de scripts).

Si eso lo arregla, no tienes un bug de WordPress. Tienes una situación de sabotaje del lado del cliente.

Tareas prácticas con comandos (y decisiones)

Estas tareas asumen que tienes acceso shell al servidor (o contenedor) que aloja WordPress. Si no lo tienes, aún puedes hacer algunas comprobaciones vía navegador y admin de WordPress, pero tu velocidad estará limitada por reuniones.

Task 1: Confirmar versiones de WordPress y plugins vía WP-CLI

cr0x@server:~$ cd /var/www/html
cr0x@server:/var/www/html$ wp core version
6.6.2
cr0x@server:/var/www/html$ wp plugin list --status=active --fields=name,version
akismet 5.3.3
wp-super-cache 1.12.4
wordfence 7.11.8

Qué significa: Estás estableciendo la línea base. El comportamiento de Gutenberg depende de la versión de core y de los plugins.

Decisión: Si el core es muy antiguo (o los plugins), prioriza actualizar en un entorno de staging. Si no puedes actualizar, estarás depurando alrededor de bugs ya corregidos.

Task 2: Comprobar si la REST API es accesible desde el servidor

cr0x@server:~$ curl -sS -D- -o /dev/null https://example.com/wp-json/
HTTP/2 200
content-type: application/json; charset=UTF-8
cache-control: no-cache, must-revalidate, max-age=0

Qué significa: 200 y content-type JSON es el camino feliz.

Decisión: Si obtienes 301/302 en bucle, arregla site URL o cabeceras de proxy. Si content-type es text/html, algo está interceptando el endpoint (salida del tema/plugin, página de bloqueo del WAF o un fatal PHP volcando HTML).

Task 3: Buscar respuestas REST que son en realidad HTML (clásico asesino de Gutenberg)

cr0x@server:~$ curl -sS https://example.com/wp-json/ | head
{"name":"Example Site","description":"","url":"https:\/\/example.com","home":"https:\/\/example.com","gmt_offset":"0","timezone_string":"UTC"

Qué significa: El JSON empieza con {. Si empieza con <!doctype html> o <html, no estás recibiendo JSON.

Decisión: Si aparece HTML, revisa plugins de seguridad inyectando salida, errores del servidor o un upstream (CDN/WAF) sirviendo una página de bloqueo.

Task 4: Verificar que los scripts de wp-admin se sirvan correctamente (status, tipo, tamaño)

cr0x@server:~$ curl -sS -D- -o /dev/null "https://example.com/wp-admin/load-scripts.php?c=0&load[]=wp-blocks,wp-element,wp-editor"
HTTP/2 200
content-type: application/javascript; charset=UTF-8
cache-control: private, max-age=0, no-store, no-cache, must-revalidate

Qué significa: Los scripts del editor deben volver como JavaScript, no HTML ni una “página de desafío” cacheada.

Decisión: Si el content-type es incorrecto, para. Arregla caché/minificación/reescritura CDN antes de tocar WordPress.

Task 5: Buscar fatales de PHP alrededor del momento en que falla el editor

cr0x@server:~$ sudo tail -n 80 /var/log/php8.2-fpm.log
[27-Dec-2025 10:41:12] WARNING: [pool www] child 2314 said into stderr: "PHP Warning:  Undefined array key "foo" in /var/www/html/wp-content/plugins/some-plugin/plugin.php on line 91"
[27-Dec-2025 10:41:12] WARNING: [pool www] child 2314 said into stderr: "PHP Fatal error:  Uncaught Error: Call to undefined function wp_get_environment_type() in /var/www/html/wp-content/plugins/some-plugin/plugin.php:132"

Qué significa: Errores fatales pueden romper respuestas REST y cargadores de scripts, causando que Gutenberg falle indirectamente.

Decisión: Si ves fatales, desactiva el plugin/tema que los causa. No intentes “rodear” fatales.

Task 6: Revisar el log de debug de WordPress en busca de pistas REST/editor

cr0x@server:~$ sudo tail -n 80 /var/www/html/wp-content/debug.log
[27-Dec-2025 10:41:11 UTC] WordPress database error Deadlock found when trying to get lock; try restarting transaction for query UPDATE `wp_options` SET `option_value` = '...' WHERE `option_name` = '_transient_timeout_wp_core_block_patterns'
[27-Dec-2025 10:41:12 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/some-plugin/plugin.php:91)

Qué significa: Deadlocks y “headers already sent” frecuentemente se traducen en JSON roto.

Decisión: Arregla contenido de contención en la base de datos (o elimina el código que causa actualizaciones repetidas de opciones). Corrige “headers already sent” eliminando salidas inesperadas, BOMs o plugins ruidosos.

Task 7: Desactivar todos los plugins rápidamente (luego reactivar por lotes)

cr0x@server:~$ cd /var/www/html
cr0x@server:/var/www/html$ wp plugin deactivate --all
Success: Deactivated 27 of 27 plugins.

Qué significa: Acabas de reducir dramáticamente el espacio del problema.

Decisión: Si Gutenberg ahora carga, reactiva plugins en grupos de 3–5 hasta que falle. El último lote contiene al culpable.

Task 8: Cambiar a un tema por defecto para eliminar personalizaciones de editor a nivel de tema

cr0x@server:~$ cd /var/www/html
cr0x@server:/var/www/html$ wp theme list --status=active
+----------------+----------+-----------+---------+
| name           | status   | update    | version |
+----------------+----------+-----------+---------+
| corp-theme     | active   | none      | 4.9.1   |
+----------------+----------+-----------+---------+
cr0x@server:/var/www/html$ wp theme activate twentytwentyfour
Success: Switched to 'Twenty Twenty-Four' theme.

Qué significa: Muchos “temas corporativos” añaden scripts de admin/editor, estilos de bloque o cabeceras CSP.

Decisión: Si el tema por defecto lo arregla, compara qué hace el tema en functions.php: scripts enqueued, filtros REST, cabeceras de seguridad y hooks del editor.

Task 9: Validar patrones de estado HTTP en logs del servidor web (endpoints REST y scripts de admin)

cr0x@server:~$ sudo awk '$7 ~ /wp-json|load-scripts.php|admin-ajax.php/ {print $4, $7, $9}' /var/log/nginx/access.log | tail -n 20
[27/Dec/2025:10:41:10 /wp-json/wp/v2/types?context=edit 403
[27/Dec/2025:10:41:10 /wp-admin/load-scripts.php?c=0&load[]=wp-blocks,wp-element,wp-editor 200
[27/Dec/2025:10:41:11 /wp-json/wp/v2/settings 403
[27/Dec/2025:10:41:12 /wp-json/wp/v2/users/me?context=edit 403

Qué significa: Repetidos 403 en /wp-json/wp/v2/* sugieren fuertemente WAF/plugin de seguridad/malconfiguración de capacidades.

Decisión: Si los 403 coinciden con cargas del editor, enfócate en autenticación, nonces y reglas de seguridad—no en los bundles JS.

Task 10: Comprobar si tu proxy reverso envía correctamente el esquema/host (ruptura común de nonces/cookies)

cr0x@server:~$ sudo grep -R "fastcgi_param\|proxy_set_header" -n /etc/nginx/sites-enabled | head -n 40
/etc/nginx/sites-enabled/example.conf:42:proxy_set_header Host $host;
/etc/nginx/sites-enabled/example.conf:43:proxy_set_header X-Forwarded-Proto $scheme;
/etc/nginx/sites-enabled/example.conf:44:proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

Qué significa: Si WordPress piensa que está en HTTP mientras los usuarios están en HTTPS, obtienes cookies mixtas, redirecciones erróneas y fallos de validación de nonces.

Decisión: Si estás detrás de un load balancer/ingress, confirma que X-Forwarded-Proto y WordPress siteurl/home coinciden con la realidad.

Task 11: Comprobar saturación de PHP-FPM (la latencia hace que “cargar para siempre” parezca un problema JS)

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 Fri 2025-12-27 08:12:04 UTC; 2h 31min ago
     Status: "Processes active: 42, idle: 0, Requests: 19832, slow: 117"

Qué significa: “idle: 0” y un conteo de requests lentos en aumento indica saturación. Gutenberg dispara muchas peticiones administrativas; amplifica los cuellos de botella.

Decisión: Si está saturado, inspecciona los slow logs, aumenta cuidadosamente los children de FPM y aborda causas raíz (DB lenta, disco lento, plugins pesados) antes de añadir workers y consumir RAM.

Task 12: Comprobar espacio en disco y presión de inodos (problemas aburridos causan incidencias excitantes)

cr0x@server:~$ df -h /var/www/html
Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme0n1p2  100G   96G  4.0G  96% /
cr0x@server:~$ df -i /var/www/html
Filesystem       Inodes  IUsed   IFree IUse% Mounted on
/dev/nvme0n1p2  6553600 6501021 52579   99% /

Qué significa: Discos casi llenos o agotamiento de inodos pueden romper actualizaciones de plugins, escrituras de caché, archivos de sesión y archivos temporales usados por PHP.

Decisión: Si >90% usado o inodos >95%, trátalo como un incidente prioritario: libera espacio, rota logs, purga cachés y arregla el crecimiento.

Task 13: Probar la capacidad de respuesta de la base de datos y revisar bloqueo de tablas

cr0x@server:~$ mysql -u root -p -e "SHOW FULL PROCESSLIST\G" | sed -n '1,80p'
*************************** 1. row ***************************
     Id: 1432
   User: wpuser
   Host: 127.0.0.1:59314
     db: wordpress
Command: Query
   Time: 18
  State: Sending data
   Info: SELECT option_name, option_value FROM wp_options WHERE autoload = 'yes'

Qué significa: Consultas de larga duración en wp_options (autoload) son un vector clásico de lentitud administrativa. Gutenberg se sentirá “roto” cuando en realidad esté expirando por tiempo.

Decisión: Si la consulta de autoload es lenta, audita el tamaño de las opciones autoload, elimina basura y arregla plugins que spamean opciones.

Task 14: Revisar tamaño de opciones autoload (el ancla invisible)

cr0x@server:~$ mysql -u root -p wordpress -e "SELECT ROUND(SUM(LENGTH(option_value))/1024/1024,2) AS autoload_mb FROM wp_options WHERE autoload='yes';"
autoload_mb
12.47

Qué significa: Las opciones autoload se cargan en cada petición. Doble dígito en MB no es “aceptable.” Es un impuesto de latencia.

Decisión: Si el autoload es grande, identifica a los mayores responsables y desactiva/ajusta los plugins que agregan entradas autoload enormes.

Task 15: Identificar las opciones autoload más grandes (encuentra el plugin responsable)

cr0x@server:~$ mysql -u root -p wordpress -e "SELECT option_name, ROUND(LENGTH(option_value)/1024,1) AS kb FROM wp_options WHERE autoload='yes' ORDER BY LENGTH(option_value) DESC LIMIT 15;"
option_name	kb
some_plugin_cache	2048.0
theme_mods_corp-theme	1536.4
wpseo_titles	412.7

Qué significa: Ahora tienes nombres. Los nombres son accionables.

Decisión: Para caches de plugin enormes, cámbialos a non-autoload o purga. Para theme mods, considera si el tema está almacenando demasiado y si el editor de sitio lo está amplificando.

Task 16: Temporalmente evitar la caché de objetos para ver si Redis/Memcached está envenenando el admin

cr0x@server:~$ cd /var/www/html/wp-content
cr0x@server:/var/www/html/wp-content$ ls -l object-cache.php
-rw-r--r-- 1 www-data www-data  48210 Dec 10 09:14 object-cache.php
cr0x@server:/var/www/html/wp-content$ sudo mv object-cache.php object-cache.php.disabled

Qué significa: WordPress usa wp-content/object-cache.php como drop-in. Renombrarlo lo desactiva.

Decisión: Si Gutenberg funciona tras desactivar la caché de objetos, tu backend de caché o drop-in está defectuoso/misconfigurado. Arréglalo; no dejes la caché desactivada para siempre a menos que te guste pagar facturas de DB caras.

Task 17: Confirmar que las cabeceras no estén bloqueando scripts (CSP es una auto-lesión frecuente)

cr0x@server:~$ curl -sS -D- -o /dev/null https://example.com/wp-admin/post-new.php | egrep -i "content-security-policy|x-frame-options|x-content-type-options"
content-security-policy: default-src 'self'; script-src 'self'; object-src 'none'
x-content-type-options: nosniff

Qué significa: Un script-src 'self' estricto puede romper el admin de WordPress porque el core depende de scripts inline en sitios y de chunks cargados dinámicamente.

Decisión: Si la CSP es estricta, ajústala específicamente para wp-admin (o retírala allí). La seguridad es buena; romper tu editor no es “seguro”, es simplemente incómodo.

Task 18: Comprobar contenido mixto o forzado HTTP en la configuración de WordPress

cr0x@server:~$ wp option get siteurl
https://example.com
cr0x@server:~$ wp option get home
https://example.com

Qué significa: Si estos son HTTP mientras tu admin es HTTPS, tendrás desajustes de activos y comportamiento extraño de cookies.

Decisión: Arregla siteurl/home y las cabeceras de proxy. Luego limpia cachés.

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

1) Síntoma: Spinner infinito “Cargando…” en el editor

Causa raíz: Llamadas a la REST API devolviendo 403 (WAF/plugin de seguridad) o HTML en lugar de JSON.

Solución: Verifica /wp-json/ y /wp-json/wp/v2/users/me?context=edit en DevTools → Red. Lista blanca endpoints REST en el WAF, ajusta reglas de plugins de seguridad o arregla fatales PHP que producen salida HTML.

2) Síntoma: “El editor ha encontrado un error inesperado” tras actualizar un plugin

Causa raíz: El plugin enqueuea scripts en wp-admin incorrectamente (dependencias erróneas, React conflictivo o sobrescritura de variables globales).

Solución: Desactiva el plugin. Si debes mantenerlo, asegúrate de que no incluya su propia copia de React o empaquete incorrectamente paquetes de WordPress; actualízalo a una versión compatible.

3) Síntoma: El editor funciona para administradores, falla para editores/autores

Causa raíz: Restricciones de capacidades/roles que bloquean endpoints REST con context=edit, a menudo por plugins de membresía o código personalizado.

Solución: Compara respuestas REST por rol. Arregla el mapeo de capacidades y no bloquees a lo bruto los endpoints wp/v2.

4) Síntoma: El editor carga solo en incógnito

Causa raíz: Extensiones de navegador, activos rotos en caché o interferencia de service worker.

Solución: Desactiva extensiones, borra datos del sitio y asegúrate de que los assets de admin no estén cacheados por CDN. Verifica cache-control en load-scripts.php que sea private/no-store.

5) Síntoma: “Actualización fallida. La respuesta no es un JSON válido.”

Causa raíz: La llamada REST de guardado devuelve HTML (salida de warning PHP, página de bloqueo del WAF o página de error 500).

Solución: Mira el cuerpo de la petición fallida en la red. Arregla la advertencia/fatal PHP, desactiva el plugin que imprime salida o lista blanca el endpoint en el WAF.

6) Síntoma: Gutenberg solo falla en posts grandes

Causa raíz: post_content enorme, muchos bloques, shortcodes pesados o agotamiento de memoria durante el parse/ render del marcado de bloques.

Solución: Aumenta memoria PHP y max execution time con precaución, elimina bloques/shortcodes patológicos, divide contenido y limpia revisiones.

7) Síntoma: El editor se rompió justo después de una “optimización de rendimiento”

Causa raíz: Plugin de minificación/diferimiento aplicado a wp-admin, o CDN cacheando wp-admin/load-scripts.php.

Solución: Excluye wp-admin y load-scripts.php de la optimización. Asegúrate de que el edge respete las cabeceras private/no-store para admin.

8) Síntoma: Fallos aleatorios, especialmente bajo carga

Causa raíz: Saturación de PHP-FPM, DB lenta, inestabilidad de caché de objetos, latencia de disco o agotamiento de inodos.

Solución: Trátalo como un incidente de rendimiento: revisa estado FPM, slow logs, processlist DB, espacio/disco/inodos. Arregla capacidad y puntos calientes.

Listas de verificación / plan paso a paso

Checklist A: Depurar que Gutenberg no carga (15–30 minutos)

  1. Consola del navegador: captura el primer error en rojo. No el décimo. El primero suele importar.
  2. Pestaña Red: identifica la primera petición que falla (a menudo /wp-json/, /wp-json/wp/v2/settings o /wp-admin/load-scripts.php).
  3. Confirmar en servidor: curl al endpoint fallido y verificar estado y content-type.
  4. Desactivar plugins: wp plugin deactivate --all.
  5. Cambiar tema: activar temporalmente un tema por defecto.
  6. Bypass de cachés: desactivar drop-in de caché de objetos; evitar CDN si es posible (host header directo al origen o ruta VIP interna).
  7. Revisar logs: log de PHP-FPM + log de errores web + debug.log de WordPress.
  8. Restaurar incrementalmente: reactivar plugins por lotes, luego tema, luego caches.

Checklist B: Cuando falla el guardado pero el editor carga

  1. En DevTools, localiza la petición de guardado que falla (a menudo POST a /wp-json/wp/v2/posts/ID).
  2. Inspecciona el cuerpo de la respuesta: ¿es HTML (página de error), JSON (con código de error) o vacío?
  3. Revisa cabeceras de autenticación/cookies: ¿está el usuario autenticado? ¿Hay SSO o proxy reverso reescribiendo cookies?
  4. Busca en logs del servidor 401/403/500 en el tiempo de esa petición.
  5. Desactiva temporalmente reglas WAF que afecten POST/endpoints JSON.
  6. Confirma que la generación de nonces no esté cacheada (las páginas admin no deberían cachearse).

Checklist C: “No carga” inducido por rendimiento (porque los timeouts parecen bugs)

  1. Revisa PHP-FPM active/idle, requests lentos y timeouts.
  2. Revisa DB: consultas largas, locks y tamaño de autoload.
  3. Revisa disco: espacio, inodos y síntomas de latencia I/O (queue depth, await alto).
  4. Desactiva primero los plugins administrativos más pesados (page builders, dashboards de analítica, scanners de seguridad).
  5. Sólo entonces ajusta timeouts/memoria. Aumentar límites sin arreglar lentitud sólo prolonga el sufrimiento.

Broma #2: Cuando alguien dice “no cambié nada”, asumo que quiere decir “cambié algo y no lo anoté”.

Tres microhistorias corporativas desde el frente

Microhistoria 1: El incidente causado por una suposición equivocada

Una compañía mediana ejecutaba WordPress detrás de un load balancer y un proxy reverso nginx. La migración fue “simple”: mover tráfico, mantener el origen igual, darlo por bueno. El editor pronto empezó a colgar para algunos usuarios, pero no para todos. Naturalmente, la primera teoría fue “Gutenberg es inestable”.

La pista estaba en la traza de red: llamadas REST a /wp-json/wp/v2/users/me?context=edit devolvían 401 para algunas sesiones. Mismo usuario, resultados distintos según el nodo proxy que atendía. Eso olía a cookies.

Asumieron que la app inferiría HTTPS correctamente porque “el load balancer termina TLS”. A WordPress no le importó esa suposición. Le importó lo que veía: peticiones llegando al origen como HTTP, y WordPress generando cookies/nonces con un comportamiento desincronizado respecto a la realidad HTTPS del navegador.

La solución no fue mística. Configuraron X-Forwarded-Proto correctamente, aseguraron que WordPress lo respetara y corrigieron siteurl/home. El editor se recuperó al instante y la postmortem fue dolorosamente ordinaria: el sistema hizo exactamente lo que se le configuró para hacer, no lo que la gente creía que hacía.

Microhistoria 2: La optimización que salió mal

Otra organización quiso acelerar el admin y desplegó una regla de “caché inteligente” en el CDN: cachear cualquier petición con 200 y parámetros de consulta “estáticos”. Alguien notó que load-scripts.php y load-styles.php parecían assets estáticos. Estaban equivocados de la forma que causa mañanas de lunes.

Durante un tiempo pareció bien. Luego llegó una actualización menor de WordPress. El bundle de scripts de admin cacheado no coincidía con las nuevas expectativas del servidor, y de pronto Gutenberg empezó a fallar con errores JS que referenciaban módulos faltantes y funciones indefinidas.

Los ingenieros persiguieron fantasmas: conflictos de plugins, problemas de tema, bugs de navegador. La pista fue que el error solo ocurría para usuarios servidos por el edge del CDN, y desaparecía al evitar el edge. Las cabeceras de la respuesta cacheada también eran sospechosamente “public”.

La solución: nunca cachear los cargadores de scripts de wp-admin en el CDN, respetar las cabeceras private/no-store de WordPress y no tratar assets con query-string como seguros solo porque se parezcan. La “optimización” se revirtió y el admin volvió a ser aburrido—que es el estado de rendimiento correcto para un backend CMS.

Microhistoria 3: La práctica aburrida pero correcta que salvó el día

Un sitio empresarial tenía una regla operativa permanente: cada cambio que afectara caché, WAF o cabeceras de proxy reverso debía incluir una prueba previa contra tres endpoints—/wp-json/, /wp-admin/load-scripts.php y una llamada REST autenticada. No era glamoroso. No era opcional.

Una tarde, el equipo de seguridad empujó una nueva política WAF para reducir tráfico de bots. Bloqueó peticiones que parecían “enumeración de API”, lo que incluyó algunas rutas REST usadas por pantallas administrativas autenticadas. El equipo CMS no lo notó de inmediato porque las páginas front-end seguían renderizándose.

Pero la prueba pre-flight, ejecutada desde un job de CI usando una cuenta de editor de bajo privilegio, falló en minutos. El informe de falla incluía códigos HTTP y fragmentos de respuesta. Eso evitó que el equipo CMS discutiera si Gutenberg “estaba caído”; tenían evidencia.

La política WAF se ajustó con una regla de allow dirigida para tráfico wp-json autenticado, y el incidente se mantuvo pequeño. La moraleja es molesta pero predecible: las comprobaciones aburridas que automatizas son las que te salvan cuando los humanos se ponen creativos.

Preguntas frecuentes

1) ¿Por qué Gutenberg depende tanto de la REST API?

Porque es una aplicación JavaScript que obtiene y guarda contenido mediante rutas API. Si /wp-json/ está bloqueado, Gutenberg no puede cargar datos de la entrada, ajustes, información del usuario ni operaciones de guardado de forma fiable.

2) El editor funciona en mi portátil pero no para colegas. ¿Cuál es el primer sospechoso?

Cachés y capas de seguridad que varían por geografía, cookie o IP. Comportamiento del edge del CDN, desafíos WAF o proxies corporativos pueden romper selectivamente peticiones a wp-admin.

3) ¿Un solo warning de PHP puede realmente romper el editor?

Sí. Si un warning imprime salida durante una respuesta REST, tu JSON se convierte en “JSON más ruido” y Gutenberg lo trata como inválido. Arregla el warning o suprime la salida correctamente—no lo ocultes a la ligera.

4) ¿Debería instalar el plugin Classic Editor y olvidarme?

Sólo como mitigación temporal. Puede mantener a los editores trabajando mientras arreglas el problema subyacente de REST/caché/seguridad. Si lo tratas como solución permanente, estarás pagando intereses sobre un problema.

5) ¿Cuál es la forma más rápida de probar que es un conflicto de plugins?

Desactiva todos los plugins vía WP-CLI y vuelve a probar. Si funciona, reactiva por lotes. Es más rápido que leer código de plugins y fingir que te divierte.

6) ¿Podría mi base de datos ser la razón por la que Gutenberg no carga?

Absolutamente. Opciones autoload lentas, deadlocks o consultas de larga duración pueden retrasar respuestas REST hasta que la UI agote el tiempo o parezca congelada. Revisa processlist y tamaño de autoload.

7) ¿La caché de objetos ayuda o perjudica a Gutenberg?

Ambas cosas. Una caché de objetos bien configurada reduce carga DB y acelera admin. Drop-ins defectuosos o mal configurados pueden devolver datos obsoletos/incorrectos, romper nonces o producir comportamiento inconsistente. Desactívala temporalmente para aislar.

8) Recibo 403 en rutas wp-json solo en wp-admin. ¿Por qué?

Porque las llamadas REST autenticadas incluyen cookies y nonces, y las capas de seguridad a menudo las tratan distinto. Reglas WAF que son aceptables para GET anónimos pueden bloquear rutas API autenticadas usadas por el editor.

9) ¿Es mala idea usar CSP en wp-admin?

No inherentemente, pero es fácil hacerlo mal. Si estableces una política estricta sin acomodar los patrones de scripts del admin de WordPress, bloquearás funcionalidades core. Aplica CSP con cuidado y prueba el editor.

10) Mi sitio está en multisite. ¿Hay modos de fallo especiales de Gutenberg?

Sí: desajustes de mapeo de dominios, problemas de scope de cookies entre subdominios y plugins activados en la red que afectan comportamiento REST. Prueba la REST API y el editor en varios subsites y roles.

Próximos pasos que puedes hacer hoy

  1. Prueba la capa: consola del navegador + pestaña Red, luego curl a los mismos endpoints desde el servidor.
  2. Haz la REST aburrida: asegúrate de que /wp-json/ devuelva JSON con 200, no redirecciones, no HTML, ni teatro del WAF.
  3. Aísla variables: desactiva plugins, cambia a un tema por defecto, evita caché de objetos, evita CDN/WAF.
  4. Arregla los problemas de infraestructura: saturación PHP-FPM, presión de disco, bloat de autoload DB y cabeceras de proxy mal configuradas.
  5. Fija prevención: añade una comprobación automática simple que golpee endpoints REST y scripts de admin después de cambios en caché/WAF/proxy.

Si haces eso en ese orden, dejarás de “depurar Gutenberg” y empezarás a arreglar el sistema real que Gutenberg sólo está revelando. Y ese es todo el juego.

← Anterior
Controladores sin firma: cuando la seguridad dejó inservible hardware funcional
Siguiente →
Ubuntu 24.04 “Illegal instruction”: flags de CPU vs binarios — arreglar despliegues de forma limpia (caso #56)

Deja un comentario