El editor de WordPress muestra “Invalid JSON response” y de repente tu “actualización de contenido simple” se convierte en un incidente de producción.
Las entradas no se publican. Las opciones no se guardan. El Editor de Bloques se enfada. Y la consola del navegador está en silencio pero gritando sobre llamadas REST que fallan.
Este error no es un misterio. Es un síntoma: WordPress esperaba JSON del REST API, pero recibió otra cosa—una página de inicio de sesión HTML,
un 403 de un WAF, un bucle de redirección, una falla TLS, un 404 cacheado o un plugin que “amablemente” reescribe cabeceras.
Lo trataremos como un problema SRE: observa, acota, prueba, arregla, previene.
Qué significa realmente “Invalid JSON response”
WordPress (especialmente el Editor de Bloques/Gutenberg) se comunica con tu propio sitio usando el REST API. Hace peticiones HTTP a endpoints como
/wp-json/wp/v2/posts. Espera que el cuerpo de la respuesta sea JSON válido y que el código de estado HTTP indique éxito
(normalmente 200/201).
Cuando eso no ocurre—porque la respuesta es HTML, está vacía, truncada, redirigida, bloqueada o servida desde el host equivocado—lanza
el genérico mensaje “Invalid JSON response”. Ese mensaje es básicamente WordPress diciendo: “Pedí JSON y la realidad discrepa.”
Tu tarea es averiguar qué devolvió realmente la realidad. Eso siempre es visible en un lugar: la respuesta de red para la llamada REST
(código de estado, cabeceras, cuerpo). Si estás adivinando, estás perdiendo el tiempo.
Una cita que vale la pena recordar al depurar esto: idea parafraseada
— Charity Majors: “No puedes mejorar lo que no mides.”
El error del editor no es una medición. El intercambio HTTP sí lo es.
Guía rápida de diagnóstico (primeras/segundas/terceras comprobaciones)
Primero: confirma la petición fallida y qué devolvió
- Abre DevTools del navegador → Red (Network).
- Dispara la acción de guardar/publicar que falla.
- Encuentra la petición a
/wp-json/(a menudo/wp-json/wp/v2/posts/<id>o/wp-json/wp/v2/settings). - Lee: código de estado, cuerpo de la respuesta y cualquier redirección.
Decisión: Si el cuerpo de la respuesta es HTML (página de inicio de sesión, página de error, página de bloqueo de WAF), no estás tratando con “parsing de JSON.”
Estás tratando con autenticación, enrutamiento, filtrado de seguridad, caché o reescritura upstream.
Segundo: consulta el REST API directamente desde tu estación de trabajo
Usa curl contra un endpoint simple como /wp-json/ y uno real como /wp-json/wp/v2/types/post.
Hazlo con y sin autenticación (si es necesaria). Esto separa “rariedades del navegador/CORS” de “el servidor está roto.”
Tercero: evita capas
Los sitios WordPress rara vez son “solo WordPress.” Tienen un CDN, un proxy inverso, un WAF, caché y una jungla de plugins.
Evita capas en este orden:
- Evitar el CDN (acceder al origen directamente vía hosts file o un hostname de origen).
- Evitar la caché (envía
Cache-Control: no-cache; desactiva el caché de página temporalmente). - Desactivar plugins (apunta primero a seguridad, caché y plugins de cabeceras).
- Cambiar a un tema por defecto (sí, los temas pueden romper el REST).
Decisión: en el momento en que la respuesta REST vuelva a ser JSON correcto, has identificado la capa a investigar. No vuelvas a activar todo a la vez.
Haz un cambio por vez. Estás depurando, no realizando una danza interpretativa.
Hechos interesantes y contexto histórico (por qué sigue ocurriendo)
- El REST API no siempre fue parte del core. Las capacidades del REST API de WordPress evolucionaron mediante plugins antes de integrarse al core, así que los ecosistemas antiguos tienen “opiniones” al respecto.
- Gutenberg subió la apuesta. El Editor de Bloques depende mucho del REST; los flujos del editor clásico tocaban menos endpoints y ocultaban muchos problemas del servidor.
- “Invalid JSON” a menudo significa “ocurrió HTML”. Un formulario de login, una página de error 403 o un documento “Acceso denegado” del WAF es HTML válido e invalida el JSON—WordPress lo reporta igual.
- Los ajustes de permalinks son operativos. Las reglas de reescritura no son “solo SEO.” Una configuración rota de reescritura puede convertir rutas de API en 404, y el editor pierde la cabeza.
- CORS se hizo más visible con navegadores modernos. El endurecimiento de políticas de navegador hizo que cabeceras cross-origin mal configuradas fallen ruidosamente, especialmente en setups headless.
- Los plugins de seguridad adoran bloquear REST. Muchos se diseñaron cuando REST era “opcional”; algunos aún tratan
/wp-json/como tráfico sospechoso. - Los CDNs cachean más de lo que crees. Una caché mal configurada puede almacenar un 301/302/403/404 para rutas de API y servirlo a todo el mundo, incluidos administradores.
- HTTP/2 y proxies cambiaron las formas de fallo. Algunas combinaciones edge/proxy producen comportamientos de cabeceras y redirecciones que confunden a clientes que esperan endpoints estables.
- El contenido mixto no ha muerto. Sitios que migran parcialmente a HTTPS todavía pueden disparar solicitudes REST a HTTP en esquinas raras (site URL vs home URL vs cabeceras del proxy inverso).
Los grandes modos de fallo: SSL, CORS, plugins, proxies, caché
1) SSL/TLS y “esquema incorrecto” (HTTP vs HTTPS)
Un clásico: tu página de administración carga por HTTPS, pero WordPress genera URLs REST con HTTP (o viceversa).
Los navegadores pueden bloquear contenido mixto, o la petición sigue redirecciones y devuelve HTML.
Causas raíz comunes:
- Desajuste Site URL/Home URL en los ajustes de WordPress o en la base de datos.
- Proxy inverso que no reenvía correctamente
X-Forwarded-Proto; WordPress piensa que está en HTTP. - HSTS y forzado de HTTPS causando redirecciones extras o bucles de redirección cacheados.
- Desajuste de certificado para el hostname usado por las llamadas REST (www vs apex).
2) Problemas de CORS (especialmente en setups headless o admin inusual)
Si tu interfaz de administración se hospeda en un origen y la API de WordPress en otro, el navegador aplica CORS.
Cuando CORS falla, a menudo ves que la UI de WordPress reporta “Invalid JSON response” porque la llamada API nunca devuelve JSON legible para JS.
Disparadores típicos de CORS:
- Usar un dominio distinto para admin que para API (p. ej., host de admin personalizado, host de staging, puertos no estándar).
- Falta de
Access-Control-Allow-Origino valor incorrecto. - Preflight OPTIONS bloqueado por el servidor/WAF.
- Modo con credenciales (cookies) que requiere
Access-Control-Allow-Credentials: truey un origin no wildcard.
3) Plugins y temas: el sabotaje “útil”
Una cantidad deprimente de fallos REST son autoinfligidos:
- Plugins de seguridad que bloquean endpoints REST por nonces o límites de tasa.
- Plugins de caché que cachean respuestas de API o reescriben cabeceras.
- Plugins de optimización/minificación que rompen
wp-api-fetcho la inyección de nonces. - Temas que añaden salida antes de las cabeceras (warnings/notices de PHP) que corrompen la salida JSON.
Chiste #1: La forma más rápida de reproducir un “Invalid JSON response” es instalar tres plugins “imprescindibles” de un post de blog escrito en 2016.
4) Proxies inversos, CDNs y WAFs: las middleboxes
Los proxies inversos y CDNs son geniales hasta que deciden que tu petición REST necesita “mejora”:
- Redirecciones 301/302 aplicadas a rutas
/wp-json/. - Reglas WAF (ModSecurity o WAF gestionados) que bloquean POST/PUT con cuerpos JSON.
- Límites de tamaño de cabecera, límites del cuerpo de la petición o timeouts que cortan respuestas.
- Claves de caché que ignoran cookies; sirven respuestas cacheadas anónimas a llamadas de administrador.
5) Permalinks y reescrituras: aburrido, letal
Cuando las reglas de reescritura están mal, las rutas REST pueden convertirse en 404 o enrutarse al archivo equivocado. WordPress entonces devuelve HTML
(una plantilla 404, o una redirección), y el editor lo llama “Invalid JSON.”
Los problemas de reescritura son comunes después de:
- Migrar de Apache a Nginx sin reglas equivalentes.
- Cambiar el document root o añadir una instalación en subdirectorio.
- Habilitar multisite, o cambiar el mapeo de dominios.
6) Autenticación/nonces y “te desloguearon”
Los endpoints REST de WordPress a menudo requieren un nonce válido para acciones de administrador. Si las cookies no están bien configuradas (dominio, flag secure),
o si un proxy elimina cabeceras, las llamadas REST pueden devolver 401/403. A veces el cuerpo es HTML (redirección al login).
Tareas prácticas: comandos, salidas, decisiones (12+)
El propósito de estas tareas no es teclear comandos por diversión. Cada una te dice algo específico y te fuerza a tomar una decisión.
Ejecútalas desde un shell con acceso al servidor cuando sea posible. Cuando no sea posible, ejecuta las variantes cliente desde tu estación.
Tarea 1: Confirma que el endpoint raíz REST devuelve JSON
cr0x@server:~$ curl -sS -D- https://example.com/wp-json/ -o /tmp/wpjson.body | head -n 20
HTTP/2 200
content-type: application/json; charset=UTF-8
x-robots-tag: noindex
vary: Origin
date: Fri, 27 Dec 2025 10:12:05 GMT
cr0x@server:~$ head -c 180 /tmp/wpjson.body
{"name":"Example Site","description":"Just another WordPress site","url":"https:\/\/example.com","home":"https:\/\/example.com","gmt_offset":0,
Qué significa: 200 + application/json + cuerpo JSON indica salud en el endpoint base.
Decisión: Si esto falla (no-200 o HTML), enfócate en routing/WAF/SSL antes de tocar internals de WordPress.
Tarea 2: Comprueba una ruta REST real usada por Gutenberg
cr0x@server:~$ curl -sS -D- https://example.com/wp-json/wp/v2/types/post -o /tmp/types.body | head -n 20
HTTP/2 200
content-type: application/json; charset=UTF-8
cache-control: no-cache, must-revalidate, max-age=0
date: Fri, 27 Dec 2025 10:12:10 GMT
cr0x@server:~$ jq -r '.slug,.rest_base' /tmp/types.body
post
posts
Qué significa: Endpoints core son alcanzables y devuelven JSON parseable.
Decisión: Si obtienes 401/403 aquí, sospecha de auth/nonces, WAF o plugins de seguridad. Si 404, sospecha de rewrites/permalinks/proxy routing.
Tarea 3: Detecta bucles de redirección o confusión de esquema
cr0x@server:~$ curl -sS -I -L https://example.com/wp-json/ | egrep -i 'HTTP/|location:'
HTTP/2 301
location: http://example.com/wp-json/
HTTP/1.1 301 Moved Permanently
location: https://example.com/wp-json/
Qué significa: Tienes una redirección ping-pong entre HTTP y HTTPS.
Decisión: Arregla cabeceras del proxy y ajustes de URL de WordPress antes que nada. Los bucles de redirección no son “menores.”
Tarea 4: Verifica que el certificado TLS coincida con el host usado por llamadas REST
cr0x@server:~$ echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -subject -issuer -dates
subject=CN = example.com
issuer=CN = R3, O = Let's Encrypt, C = US
notBefore=Dec 1 00:00:00 2025 GMT
notAfter=Feb 29 23:59:59 2026 GMT
Qué significa: El certificado es válido para el hostname.
Decisión: Si CN/SAN no coinciden (p. ej., solo www), alinea el host canónico o instala un certificado que cubra ambos.
Tarea 5: Comprueba los valores “home” y “siteurl” de WordPress (CLI)
cr0x@server:~$ cd /var/www/html
cr0x@server:~$ wp option get home
https://example.com
cr0x@server:~$ wp option get siteurl
http://example.com
Qué significa: Desajuste. Las URLs REST pueden construirse desde siteurl en algunos contextos.
Decisión: Hazlas consistentes (normalmente ambas HTTPS) y asegúrate de que el proxy inverso reporte HTTPS correctamente.
Tarea 6: Arregla las URLs de WordPress de forma segura (CLI)
cr0x@server:~$ wp option update home 'https://example.com'
Success: Updated 'home' option.
cr0x@server:~$ wp option update siteurl 'https://example.com'
Success: Updated 'siteurl' option.
Qué significa: Las URLs canónicas ahora coinciden.
Decisión: Vuelve a probar /wp-json/ y una guardada en Gutenberg. Si las redirecciones persisten, la capa proxy/CDN sigue reescribiendo.
Tarea 7: Verifica que las reglas de reescritura están presentes (flush de WordPress)
cr0x@server:~$ wp rewrite list --fields=match,query | head
^wp-json/?$ index.php?rest_route=/
^wp-json/(.*)? index.php?rest_route=/$matches[1]
^index\.php/wp-json/?$ index.php?rest_route=/
Qué significa: WordPress conoce las reescrituras REST.
Decisión: Si faltan, fuerza un flush de permalinks. Si están pero las peticiones siguen 404, las reglas del servidor web están mal.
Tarea 8: Confirma que Nginx enruta /wp-json correctamente
cr0x@server:~$ sudo nginx -T 2>/dev/null | sed -n '1,120p'
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
user www-data;
worker_processes auto;
http {
server {
listen 443 ssl http2;
server_name example.com;
root /var/www/html;
location / {
try_files $uri $uri/ /index.php?$args;
}
}
}
Qué significa: El fallback estándar try_files está presente.
Decisión: Si ves un bloque de location conflictivo que intercepta /wp-json (o devuelve 404 estático), arréglalo.
Tarea 9: Comprueba las reglas de reescritura .htaccess de Apache (si Apache)
cr0x@server:~$ sudo sed -n '1,120p' /var/www/html/.htaccess
# BEGIN WordPress
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress
Qué significa: Las reescrituras básicas de WordPress están intactas.
Decisión: Si RewriteEngine está apagado o el archivo es ignorado (AllowOverride), las rutas REST pueden fallar como 404. Arregla la configuración del vhost en consecuencia.
Tarea 10: Detecta bloqueos WAF/ModSecurity en los logs
cr0x@server:~$ sudo egrep -R "ModSecurity|Access denied|403" /var/log/apache2/ | tail -n 8
/var/log/apache2/error.log:[Wed Dec 25 09:41:12.123456 2025] [security2:error] [pid 1822] [client 203.0.113.10] ModSecurity: Access denied with code 403 (phase 2). Match of "rx (?i:select.+from)" against "ARGS:content" required. [id "942100"]
Qué significa: Una regla está bloqueando contenido en una petición REST.
Decisión: Excluye los endpoints REST de ese conjunto de reglas o ajusta las reglas para rutas admin autenticadas. No “desactives la seguridad” globalmente.
Tarea 11: Identifica si la respuesta es HTML (página de login) en vez de JSON
cr0x@server:~$ curl -sS -D- https://example.com/wp-json/wp/v2/posts -o /tmp/posts.body | head -n 15
HTTP/2 401
content-type: text/html; charset=UTF-8
date: Fri, 27 Dec 2025 10:12:55 GMT
cr0x@server:~$ head -n 5 /tmp/posts.body
Qué significa: WordPress esperaba JSON pero obtuvo HTML, probablemente una respuesta de login/auth o una página generada por un proxy.
Decisión: Arregla las cabeceras/cookies/nonces de autenticación o la regla del proxy que reescribe 401/403 en una página HTML.
Tarea 12: Valida que el preflight OPTIONS no esté bloqueado (CORS)
cr0x@server:~$ curl -sS -D- -X OPTIONS https://example.com/wp-json/wp/v2/posts \
-H 'Origin: https://admin.example.com' \
-H 'Access-Control-Request-Method: POST' \
-H 'Access-Control-Request-Headers: content-type,x-wp-nonce' \
-o /dev/null | head -n 25
HTTP/2 403
content-type: text/html; charset=UTF-8
date: Fri, 27 Dec 2025 10:13:20 GMT
Qué significa: El preflight está bloqueado. El navegador rechazará la petición real.
Decisión: Ajusta el servidor/WAF para permitir OPTIONS y devolver cabeceras CORS correctas para rutas REST.
Tarea 13: Comprueba si un CDN está cacheando respuestas de API
cr0x@server:~$ curl -sS -D- https://example.com/wp-json/ -o /dev/null | egrep -i 'cache|age|cf-|x-cache'
cache-control: max-age=14400
age: 8732
x-cache: HIT
Qué significa: Algo está cacheando el root REST durante horas.
Decisión: Excluye /wp-json/* del caching de CDN/página o establece Cache-Control: no-store para endpoints REST autenticados.
Tarea 14: Reproduce como lo ve el runtime PHP (curl local al origen)
cr0x@server:~$ curl -sS -D- http://127.0.0.1/wp-json/ -H 'Host: example.com' -o /tmp/origin.body | head -n 20
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Qué significa: El origen está bien; algo en front está rompiéndolo.
Decisión: Arregla reglas del proxy/CDN/WAF en vez de tocar ajustes de WordPress.
Tarea 15: Encuentra warnings de PHP que corrompen la salida JSON
cr0x@server:~$ sudo tail -n 30 /var/log/php8.2-fpm.log
[27-Dec-2025 10:11:41] WARNING: [pool www] child 2199 said into stderr: "PHP Warning: Undefined array key "foo" in /var/www/html/wp-content/themes/custom/functions.php on line 412"
[27-Dec-2025 10:11:41] WARNING: [pool www] child 2199 said into stderr: "PHP Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/themes/custom/functions.php:412)"
Qué significa: Se emitió salida antes de las cabeceras; la respuesta REST puede estar corrompida (JSON precedido por warnings).
Decisión: Arregla el tema/plugin que emite salida. En producción, no confíes en “ocultar warnings”; elimínalos.
Tarea 16: Aislamiento rápido de plugins sin desinstalar (CLI)
cr0x@server:~$ wp plugin list --status=active
+----------------------+----------+-----------+---------+
| name | status | update | version |
+----------------------+----------+-----------+---------+
| wordfence | active | none | 7.11.0 |
| wp-rocket | active | none | 3.16.0 |
| redis-cache | active | none | 2.5.3 |
| custom-mu-plugin | active | none | 1.0.0 |
+----------------------+----------+-----------+---------+
cr0x@server:~$ wp plugin deactivate wordfence wp-rocket
Plugin 'wordfence' deactivated.
Plugin 'wp-rocket' deactivated.
Qué significa: Puedes probar el comportamiento REST con menos partes móviles.
Decisión: Si el problema desaparece, vuelve a activar uno a uno. Si no, no culpes a los plugins por costumbre—pasa a proxy/SSL/routing.
Chiste #2: “Invalid JSON response” es la forma en que WordPress te dice que tu infraestructura tiene opiniones—y está de mal humor.
Errores comunes: síntoma → causa raíz → solución
1) Síntoma: El editor no publica; Red muestra 301/302 y luego HTML
Causa raíz: Canonicalización de esquema/host redirigiendo endpoints REST (HTTP↔HTTPS, www↔apex), a veces en bucle.
Solución: Alinea home y siteurl al host canónico HTTPS; arregla cabeceras del proxy (X-Forwarded-Proto), y deja de especializar /wp-json distinto al tráfico normal de páginas.
2) Síntoma: La petición REST devuelve 403 con una página HTML de “bloqueado”
Causa raíz: Regla WAF/ModSecurity activada por payload JSON, contenido del post o patrones de ruta REST.
Solución: Ajusta el WAF: permite rutas REST autenticadas, permite OPTIONS, y aplica excepciones de forma estrecha a /wp-json/ y usuarios admin. Verifica en logs.
3) Síntoma: La petición REST devuelve 401; el cuerpo parece la página de login
Causa raíz: Fallo de autenticación/nonces por dominio/flags secure de cookies, caché mezclando anónimo/admin o proxy que elimina cabeceras.
Solución: Asegura cookies admin como secure bajo HTTPS, excluye REST del page caching y confirma el reenvío de la cabecera Authorization (especialmente con Apache/Nginx + PHP-FPM).
4) Síntoma: El endpoint REST devuelve 404, pero las páginas del sitio funcionan
Causa raíz: Las reglas de reescritura de WordPress no se aplican (config Nginx mala, .htaccess ignorado), o una regla conflictiva intercepta /wp-json.
Solución: Corrige el routing del servidor web para pasar paths desconocidos a index.php; fuerza flush de permalinks; verifica que /wp-json/ devuelva JSON.
5) Síntoma: Funciona en origen, falla a través del CDN
Causa raíz: Caché del CDN o diferencias de política de seguridad en el edge. A veces el edge inyecta redirecciones o bloquea POST.
Solución: Evita el CDN para confirmar; luego configura reglas edge para no cachear /wp-json/*, permitir métodos REST y reenviar cabeceras/cookies necesarias.
6) Síntoma: Fallos aleatorios; a veces “invalid JSON”, a veces OK
Causa raíz: Timeouts upstream intermitentes, saturación de PHP-FPM o condiciones de carrera en caché que devuelven respuestas parciales/truncadas.
Solución: Revisa timeouts upstream y salud de PHP-FPM; aumenta límites con cuidado; arregla plugins/DB lentos; deja de cachear admin y respuestas REST.
7) Síntoma: La respuesta es JSON pero el editor aún muestra error
Causa raíz: JSON malformado (warnings de PHP inyectados), o la respuesta es comprimida/truncada por un proxy; a veces aparecen problemas de charset o BOM por código custom.
Solución: Busca warnings/notices de PHP, desactiva hacks de buffering de salida y confirma que el cuerpo bruto de la respuesta empieza con { o [ y está completo.
8) Síntoma: Solo un usuario admin lo ve; otros no
Causa raíz: Extensiones del navegador, cookies viejas, camino de red diferente (VPN) o un trigger de WAF/límite por usuario.
Solución: Compara cabeceras y respuestas entre usuarios; prueba en un perfil de navegador limpio; revisa logs WAF indexados por IP/user-agent.
Tres microhistorias corporativas de vida real en operaciones
Microhistoria 1: El incidente causado por una suposición errónea
Un equipo de marketing lanzó un cambio “pequeño” de dominio: mover el blog de blog.example.com a www.example.com/blog.
El plan de migración trataba sobre redirecciones y SEO. Todos aceptaron que el editor seguiría funcionando porque “es la misma instancia de WordPress.”
La primera señal de problemas no fue un error 500 o una caída del sitio. Fue que los editores no podían publicar. “Invalid JSON response” apareció
al guardar posts, pero el frontend se renderizaba bien. La suposición fue que el REST API seguiría las mismas redirecciones que el navegador.
Lo hizo—directo a una página de login con un scope de cookie distinto.
Las llamadas REST estaban siendo redirigidas desde /blog/wp-json/ a /wp-json/ en el edge, y las cookies definidas para
blog.example.com no se enviaban a www.example.com. WordPress trató las peticiones autenticadas como anónimas,
devolvió HTML de login y Gutenberg reportó JSON inválido.
Arreglarlo no fue heroico: establecer URLs canónicas consistentes (home/siteurl), dejar de redirigir endpoints REST de forma distinta a rutas normales,
y alinear dominios de cookie. Lo que dolió fue la demora—horas “depurando WordPress” cuando el problema era una cuestión básica de consistencia origen/host.
Microhistoria 2: La optimización que salió mal
Un equipo de plataforma decidió “acelerar WordPress” cacheando más agresivamente en el CDN. La regla era simple: cachear todo lo que no parezca admin.
Alguien añadió una excepción para /wp-admin y listo.
Excepto que Gutenberg no vive solo en /wp-admin. Habla constantemente con /wp-json/, y esas peticiones llevan cookies y nonces.
El CDN, sin entender la semántica de WordPress, cacheó una respuesta 403 de una petición temprana que chocó con una regla de rate-limit. Luego sirvió ese 403 a todos.
El error del editor apareció en múltiples sitios y entornos. El frontend seguía bien—las cachés son excelentes ocultando problemas hasta que los amplifican.
El rollback fue inmediato: purge de caché, desactivar caché para /wp-json/* y dejar de cachear respuestas cuando hay cookies presentes.
Luego vino el postmortem incómodo: el equipo optimizó sin una lista explícita de rutas “nunca cachear”.
La solución duradera fue aburrida: una política de caché compartida con exclusiones explícitas para endpoints REST y flujos admin, más comprobaciones automáticas
que validan que /wp-json/ devuelva application/json y una respuesta no cacheada. El rendimiento mejoró más tarde, pero fue ganado con cuidado.
Microhistoria 3: La práctica aburrida pero correcta que salvó el día
Una compañía con múltiples propiedades WordPress tenía la costumbre que parecía exagerada: una sonda sintética pequeña que corría cada cinco minutos.
Fetchaba /wp-json/ y un endpoint autenticado representativo, y fallaba ruidosamente si el content-type no era JSON o si el cuerpo contenía <html.
Una mañana, la sonda disparó justo después de una actualización rutinaria de reglas de seguridad. Los editores aún no habían protestado, pero el sistema ya lo sabía.
El equipo de operaciones miró logs WAF y encontró requests OPTIONS bloqueadas para /wp-json, lo que habría roto el editor en ciertos navegadores y redes.
Como la sonda registró el código de estado exacto y las cabeceras de respuesta, el equipo no debatió. Desplegaron una excepción estrecha:
permitir OPTIONS y POST a /wp-json/ para sesiones autenticadas, mantener el resto de reglas intactas.
Nadie escribió un hilo dramático en Slack. El editor nunca cayó para la mayoría de usuarios. El mejor trabajo operativo a menudo parece que no pasó nada,
que es el mayor cumplido que nunca recibirás.
Listas de verificación / plan paso a paso
Paso a paso de triaje (15–30 minutos)
- Captura la llamada REST fallida en DevTools: URL, código de estado, cuerpo de la respuesta (primeros 200 bytes) y cualquier redirección.
- Prueba
/wp-json/concurly confirmaapplication/jsonen content-type y JSON válido. - Prueba un endpoint real como
/wp-json/wp/v2/types/post. Si eso falla, no pierdas tiempo con teorías específicas de Gutenberg aún. - Revisa redirecciones con
curl -I -L. Mata bucles de redirección primero. - Evita el CDN (directo al origen) y compara resultados. Si origen funciona, deja de depurar WordPress y empieza a depurar el edge.
- Revisa logs del servidor/WAF por bloqueos 401/403 alrededor del momento de tu prueba.
- Desactiva temporalmente plugins “de alto riesgo”: seguridad, caché, minify, gestores de cabeceras/CORS. Vuelve a probar.
- Revisa logs de PHP por warnings que podrían corromper respuestas JSON.
- Confirma reglas de reescritura (Nginx try_files / Apache AllowOverride + .htaccess). Vuelve a probar.
Checklist de estabilización (mismo día)
- Excluye
/wp-json/*del page caching/CDN a menos que entiendas las implicaciones. - Permite métodos REST: GET/POST/PATCH/PUT/DELETE y OPTIONS donde corresponda. Bloquea por autenticación, no solo por path.
- Estandariza host y esquema canónico (HTTPS). Ajusta
homeysiteurlde forma consistente. - Asegura que el proxy inverso establece
X-Forwarded-Protoy que la app lo confía (o termina TLS en WordPress). - Corrige warnings/notices de PHP en código de producción. “Es solo un warning” es cómo obtienes invalid JSON a las 15:00.
- Pon una sonda básica: fetch de
/wp-json/y valida JSON + content-type.
Checklist de prevención (este mes)
- Define como política las “rutas no cacheables” (no conocimiento tribal): REST, admin, login, carrito/checkout si aplica.
- Prueba cambios en edge/WAF contra endpoints REST antes del rollout.
- Mantén un set mínimo de plugins; prefiere pocos plugins bien mantenidos sobre capas apiladas de “optimización”.
- Versiona configuración de proxy y ajustes de entorno WordPress; trátalos como código de producción.
- Instrumenta: monitorea códigos HTTP para
/wp-json/*, y alerta sobre picos en 401/403/5xx.
Preguntas frecuentes
1) ¿Es “Invalid JSON response” siempre un bug de WordPress?
No. Usualmente WordPress está siendo honesto sobre una petición HTTP fallida. La mayoría de casos son redirecciones SSL, bloqueos WAF, caché o interferencia de plugins.
Empieza por la respuesta de red, no por la UI de WordPress.
2) ¿Por qué funciona el frontend mientras el editor falla?
Las páginas frontend pueden renderizarse desde HTML cacheado y tolerar redirecciones. El editor necesita endpoints REST, auth correcta y respuestas JSON.
Puedes tener un sitio con buena apariencia y con el plano de control roto.
3) ¿Cuál es la prueba más rápida?
Fetch de /wp-json/ y verifica que recibes 200 y Content-Type: application/json, más un cuerpo JSON.
Si obtienes HTML, tienes un problema de enrutamiento/auth/seguridad.
4) ¿Puede CORS causar esto incluso en un sitio WordPress normal?
Sí, si la interfaz admin o las peticiones API se originan en un dominio/puerto diferente (hosts admin personalizados, setups headless, staging con origen distinto).
Fallos de CORS pueden aparecer como “invalid JSON” porque JS no puede leer la respuesta.
5) ¿Los plugins de caché suelen romper REST?
Pueden. Los buenos intentan no hacerlo, pero la mala configuración es común. Si una capa de caché cachea /wp-json o ignora cookies, recibirás respuestas incorrectas
servidas a peticiones autenticadas. Excluye rutas REST del page cache salvo que seas deliberado.
6) ¿Por qué al desactivar un plugin de seguridad se arregla?
Algunos plugins de seguridad bloquean endpoints REST para reducir la superficie de ataque. Eso no es inherentemente incorrecto, pero suele ser demasiado agresivo para Gutenberg.
Configura listas blancas para usuarios autenticados y endpoints necesarios en lugar de bloqueos globales.
7) ¿Podría ser un problema de almacenamiento o sistema de archivos?
Indirectamente. Si el sistema sufre presión I/O y PHP hace timeout, las peticiones REST pueden fallar o devolver respuestas parciales.
Pero “Invalid JSON” rara vez es el primer síntoma de un problema de disco; normalmente verás timeouts, 502/504 y administración lenta.
8) ¿Y si REST funciona con curl pero falla en el navegador?
Eso apunta a CORS, cookies/nonces o capas solo del navegador (extensiones, bloqueo de contenido mixto, políticas de transporte estricto).
Compara cabeceras de la petición entre curl y el navegador; revisa la Consola de DevTools por errores de CORS o contenido mixto.
9) ¿Cambiar ajustes de permalinks ayuda?
A veces. “Guardar permalinks” fuerza un flush de reescrituras, lo que puede arreglar reglas faltantes tras migraciones.
Si el routing del servidor web está mal, sin embargo, ningún flush de WordPress arreglará la config de Nginx/Apache.
10) ¿Cuál es el enfoque más seguro en producción para depurar?
Evita toggles aleatorios. Captura la petición fallida, prueba origen vs edge y aísla un cambio a la vez.
Si desactivas plugins, hazlo breve y en ventanas de bajo impacto. Mejor: replica en staging con reglas proxy parecidas a producción.
Siguientes pasos que deberías tomar realmente
Si estás en medio de un incidente, sigue la guía rápida: inspecciona la petición REST que falla, haz curl /wp-json/ y evita el CDN.
Eso te dirá qué capa es culpable en minutos.
Luego arregla lo que hayas probado que está roto:
- Si ves redirecciones o cambios de esquema: alinea URLs de WordPress, corrige cabeceras del proxy y deja de tratar
/wp-jsonde forma especial. - Si ves 403/401 con cuerpos HTML: ajusta WAF/plugins de seguridad, excluye REST del caché y asegúrate de que las cabeceras/cookies de auth funcionen.
- Si ves 404: repara reescrituras en Nginx/Apache y fuerza flush de permalinks después.
- Si ves JSON malformado: elimina warnings/notices de PHP y salida antes de las cabeceras desde temas/plugins.
Finalmente, evita la repetición: añade una sonda sintética pequeña para salud REST, codifica exclusiones de caché y trata cambios en proxy/WAF como despliegues.
WordPress no es frágil. Solo está rodeado de capas que están muy seguras de sí mismas y a veces equivocadas.