Lo primero que me llegó fue una captura del navegador de la entrada de un blog corporativo de una consultora, que llevaba meses publicada ahora la mostraba comó página no encontrada. Al revisar desde el panel, el contenido seguía ahí. El artículo existía, la categoría existía, el slug no había cambiado. Pero la URL limpia no resolvía.
El sitio respondía, pero no como debía. Y lo que no encajaba era que algunas páginas sí cargaban y otras no, sin un patrón evidente. Algo se había movido por debajo sin dejar rastro visible en el panel.
Al principio no busqué culpables. Busqué diferencias. Qué URLs caían, cuáles sobrevivían, qué tenían en común y qué había pasado en el sitio antes de que empezaran los errores. Solo después de revisar el historial apareció una pista reciente: un update de WordPress aplicado dos días antes.

Operario: WordPin
Expediente del caso: El update de WordPress rompió los permalinks
Empresa o negocio: Blog corporativo de una consultora
Archivado en: Configuración de WordPress
Nivel: Intermedio
Lo que dejó de cuadrar tras el update de WordPress
Empecé por lo más básico: abrir varias URLs del blog en una ventana de incógnito y registrar qué respondía el servidor. De las quince URLs que probé, nueve devolvían 404. Las otras seis cargaban con normalidad. No había un patrón claro por categoría, fecha ni tipo de entrada. Algunas de las que fallaban llevaban meses indexadas y con tráfico constante.
Lo siguiente fue probar el acceso por ID directo. Al cambiar la URL amigable por ?p=123, el contenido aparecía. Eso descartaba un problema de base de datos o de contenido eliminado. El artículo estaba ahí, WordPress lo encontraba si le dabas la ruta interna. Pero la URL bonita no lo alcanzaba. Que una página cargue no significa que la ruta esté bien resuelta.
Revisé los logs de Apache para confirmar qué estaba pasando a nivel de servidor:
[30/May 09:14:22] "GET /estrategia-digital/plan-de-contenidos/ HTTP/1.1" 404 5123
[30/May 09:14:25] "GET /consultoria/metodologia-agil/ HTTP/1.1" 404 5123
[30/May 09:15:01] "GET /sobre-nosotros/ HTTP/1.1" 200 18340
[30/May 09:15:33] "GET /?p=214 HTTP/1.1" 200 17890
Las peticiones con slug amigable devolvían 404. Las mismas entradas por parámetro devolvían 200. La home y alguna página suelta funcionaban bien. El patrón empezaba a dibujarse, pero antes de saltar a una conclusión, necesitaba descartar otros sospechosos.
La caché como primer sospechoso habitual
El sitio tenía un plugin de caché de página activo. Era el candidato fácil: si la caché había almacenado una versión anterior de las rutas, podía estar sirviendo respuestas obsoletas o generar conflictos con las URLs reales. Purgué la caché completa desde el panel, desactivé el plugin temporalmente y volví a probar las mismas URLs en incógnito. El resultado fue exactamente el mismo. Los 404 seguían ahí, las páginas por ID seguían cargando. La caché no inventaba este problema; solo lo habría conservado si hubiera existido antes. Pero no era el origen.
Señales contradictorias después del update de WordPress
La segunda pista apuntaba al plugin SEO del sitio. Gestionaba redirecciones, canonicals y parte del comportamiento de las URLs. Un conflicto entre la configuración del plugin y la estructura de enlaces permanentes podía generar exactamente este tipo de fallo: rutas que no resuelven, contenido accesible solo por ID, y páginas sueltas que sí funcionan si el plugin las excluía de su lógica.
Desactivé el plugin SEO y repetí las pruebas. Mismo resultado. Revisé la tabla de redirecciones internas del plugin por si había reglas residuales que interfirieran con las rutas: estaba limpia. También comprobé que no hubiera redirecciones por patrón, reglas automáticas hacia la home ni ajustes aplicados solo a ciertas categorías. Sin redirecciones activas, sin reglas forzadas, sin canonicals reescritos manualmente. El plugin no estaba tocando el enrutamiento.
Esto no encajaba. Los dos sospechosos más probables estaban descartados, y el sitio seguía roto de la misma forma. La única variable reciente confirmada era la actualización del core. Pero un update de WordPress no rompe URLs por sí mismo. Lo que sí puede hacer es actuar como detonante si algo en el proceso queda incompleto.
Fui a Ajustes → Enlaces permanentes. La estructura configurada seguía siendo /%postname%/. Todo correcto en apariencia. Pero si el panel decía una cosa y las URLs decían otra, la configuración visible no era suficiente para explicar qué estaba pasando por debajo.
La estructura que WordPress creía tener
Hasta aquí, el panel mostraba la estructura de enlaces permanentes correcta. Pero las peticiones reales no la estaban usando. Esa contradicción era la clave del caso. La configuración visible en Ajustes → Enlaces permanentes refleja lo que el usuario eligió, pero no necesariamente lo que WordPress tiene almacenado internamente como reglas activas de reescritura.
Usé WP-CLI para inspeccionar directamente las reglas internas registradas en base de datos:
$ wp option get rewrite_rules --format=json | python3 -m json.tool | head -20
El resultado fue revelador. Donde debería haber decenas de reglas mapeando slugs, categorías, feeds, paginación y archivos, había apenas un puñado de entradas mínimas. Las rewrite_rules almacenadas en wp_options estaban incompletas. WordPress tenía registrada la estructura bonita en la configuración, pero el array real de reglas que usa para traducir URLs amigables en consultas internas estaba prácticamente vacío.
Eso explicaba todo el cuadro. Las URLs con slug no encontraban una regla que las tradujera, así que WordPress no sabía a qué contenido apuntaban y devolvía 404. Las URLs con ?p=123 funcionaban porque no necesitan rewrite_rules: van directo a la query interna. La home cargaba porque tiene su propia ruta prioritaria. Y las pocas páginas que sí resolvían coincidían con las escasas reglas que habían sobrevivido en el array.
La coincidencia temporal apuntaba al proceso de actualización como detonante más probable, aunque la evidencia confirmada era otra: las rewrite_rules estaban incompletas. No podía demostrar que una llamada concreta del update de WordPress hubiera roto el array, pero sí podía demostrar que WordPress conservaba la estructura visible de enlaces permanentes mientras había perdido buena parte del mapa interno que necesitaba para resolverlas.
Lo que esto significaba para el rastreo y la indexación
El impacto no era solo visual. Cada URL amigable que devolvía 404 era una página que Google ya tenía indexada. Los bots seguían llegando a rutas que ahora no resolvían, y aunque los informes aún no lo mostraban, Google Search Console acabaría registrando el problema en los siguientes ciclos de rastreo. Si el estado se mantenía, el CMS empezaría a perder visibilidad por URLs que seguían existiendo en la práctica, pero que el servidor rechazaba como si hubieran desaparecido. Un error parcial suele ser más peligroso que una caída total, porque deja suficientes piezas funcionando como para ocultar el daño mientras sigue avanzando por debajo.
La caché parecía culpable porque este tipo de fallo se parece a un problema de contenido estático desactualizado. El plugin SEO parecía sospechoso porque gestiona redirecciones y canonicals, que tocan el enrutamiento. Pero ninguno de los dos estaba interfiriendo. El fallo era más profundo: estaba en la capa de reglas internas que WordPress necesita para traducir cualquier URL amigable, y esa capa había quedado rota tras la actualización del core.
Devolver las rutas al sitio correcto
La primera idea fue directa: entrar en Ajustes → Enlaces permanentes y pulsar guardar. Eso fuerza una regeneración de las rewrite_rules desde el panel. Pero había un problema. Si el update de WordPress había dejado el sistema en ese estado, no era prudente confiar en que el mismo panel regenerara las reglas completas sin verificación posterior. En un blog corporativo con tráfico activo y URLs ya indexadas, guardar a ciegas y esperar que todo se arreglase no era una opción seria.
También existía la posibilidad de editar directamente el .htaccess desde FTP. Pero el bloque del .htaccess de WordPress es genérico: redirige las peticiones no resueltas a index.php. No contiene reglas específicas para cada estructura de permalinks. Si el fallo estaba en las reglas internas de WordPress y no en el archivo del servidor, tocar el .htaccess no iba a resolver nada. Y si se modificaba mal, se podía romper lo poco que aún funcionaba.
La corrección que no podía lanzarse a ciegas
La vía más controlada era usar WP-CLI con el flag --hard, que regenera las reglas internas y además fuerza la reescritura del bloque .htaccess. Pero antes de ejecutarlo en producción, necesitaba una referencia limpia. Accedí al entorno de staging, que no había recibido el update de WordPress todavía, y exporté el array de rewrite_rules como referencia. Eso me daba un punto de comparación fiable.
Antes de ejecutar nada, hice copia de la opción rewrite_rules y confirmé que el .htaccess no contenía reglas personalizadas.
Ejecuté el flush en producción:
$ wp rewrite flush --hard
Success: Rewrite rules flushed.
Success: Wrote .htaccess.
Después comprobé el array regenerado. Las reglas habían vuelto a poblarse con el mapa completo: slugs de entradas, categorías, paginación, feeds, archivos por fecha. Comparé con la referencia de staging y las estructuras coincidían. Luego verifiqué el .htaccess por FTP para confirmar que el bloque estándar de WordPress estaba correcto:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
El bloque era el estándar. Nada raro, nada añadido por terceros. La pieza que faltaba no era el .htaccess, sino las reglas internas que WordPress necesitaba para interpretar las peticiones que le llegaban a través de él.
Con las reglas regeneradas, fui probando una por una las URLs que habían fallado. Las nueve que antes devolvían 404 ahora resolvían con 200. Las categorías cargaban, las entradas individuales respondían, los feeds funcionaban. Revisé también Search Console para confirmar que no hubiera redirecciones inesperadas ni cambios de canonical. Todo limpio.
Antes de cerrar, purgué la caché de página, solicité un nuevo rastreo de las URLs más importantes desde Search Console y dejé un cron de monitorización básica activo durante 48 horas para confirmar estabilidad. El contenido estaba intacto. Las entradas seguían donde siempre. Lo que había desaparecido era el mapa que permitía llegar hasta ellas.
💡 Qué he aprendido
Este caso me enseñó algo que suena básico pero que en la práctica se pasa por alto: la pantalla de enlaces permanentes de WordPress puede mostrar una configuración que ya no se corresponde con lo que hay almacenado internamente. No es un fallo del panel, es que el panel refleja la elección del usuario, no el estado real de las reglas. Después de un update de WordPress, eso puede ser una trampa silenciosa.
También confirmé algo que ya intuía: los falsos positivos más peligrosos son los que encajan con el síntoma pero no con el origen. La caché y el plugin SEO parecían candidatos razonables, y en otro caso podrían haberlo sido. Pero aquí la prueba de descarte fue rápida y el fallo estaba una capa por debajo de donde parecía.
Desde este caso, cada vez que toco una actualización de core, compruebo el estado de las rewrite_rules antes de dar el update por bueno. No confío solo en que las páginas carguen. Verifico que las rutas resuelven donde deben, no solo que el servidor responde.

Cuaderno de WordPin
Forense WordPress
🧩 Notas técnicas
Blog corporativo de una consultora con estructura estable y tráfico orgánico constante. Tras una actualización del core, múltiples URLs amigables empezaron a devolver 404 mientras el panel seguía mostrando la configuración de permalinks correcta.
La causa estaba en un array de rewrite_rules almacenado de forma incompleta en wp_options. La regeneración forzada con WP-CLI restauró las reglas internas y devolvió las rutas a su estado funcional sin necesidad de tocar contenido ni configuración visible.
🔍 Pistas detectadas
- URLs con slug amigable devolvían 404, pero las mismas entradas cargaban correctamente con ?p=ID.
- La pantalla de enlaces permanentes mostraba /%postname%/ como estructura activa sin cambios visibles.
- Los logs de Apache registraban 404 en rutas amigables y 200 en rutas con parámetro directo.
- El array de rewrite_rules en wp_options contenía apenas un puñado de entradas en lugar de las decenas esperadas.
- La home y unas pocas páginas sueltas seguían resolviendo, coincidiendo con las escasas reglas que habían sobrevivido.
🚫 Errores en WordPress detectados
- rewrite_rules incompletas tras la actualización del core: las URLs amigables no encontraban traducción interna y devolvían 404, rompiendo la navegación y el rastreo.
- Discrepancia entre configuración visible y estado real: el panel mostraba la estructura correcta mientras las reglas almacenadas estaban vacías, ocultando el fallo.
- Pérdida progresiva de cobertura en Search Console: las URLs indexadas empezaron a acumular errores de rastreo, amenazando posiciones orgánicas.
- Ausencia de verificación post-update: la actualización se dio por buena sin comprobar el estado de las reglas internas ni el comportamiento real de las rutas.
📘 Glosario de WordPress
- rewrite_rules: Array almacenado en wp_options que mapea URLs amigables a consultas internas de WordPress.
- permalinks: Estructura de URLs permanentes configurada en Ajustes que define el formato público de las direcciones del sitio.
- .htaccess: Archivo de configuración de Apache que en WordPress redirige peticiones no resueltas a index.php para su procesamiento interno.
- wp rewrite flush --hard: Comando de WP-CLI que regenera las reglas internas de reescritura y fuerza la escritura del bloque .htaccess.
- wp_options: Tabla de la base de datos de WordPress que almacena configuraciones globales del sitio, incluidas las reglas de reescritura.
📏 Mini guía práctica
- Comprueba el comportamiento real de las URLs amigables después de cada actualización de core, no solo que el sitio cargue.
- Inspecciona el array de rewrite_rules en wp_options con WP-CLI o desde base de datos si hay 404 selectivos tras un update.
- Ejecuta wp rewrite flush --hard para regenerar reglas internas y forzar la reescritura del .htaccess en un solo paso.
- Verifica el bloque estándar del .htaccess por FTP para descartar modificaciones de terceros o contenido corrupto.
- Solicita un nuevo rastreo en Search Console de las URLs afectadas y monitoriza la cobertura durante las siguientes 48 horas.
Deja una respuesta
El rastro oculto del crawl budget · Serpion 001
Expedientes y Archivos