Inicio / Blog / Error 404 en WordPress por permalinks: solución automática

Error 404 en WordPress por permalinks: solución automática

Luis Ruiz

Escrito por Luis Ruiz el

¿404 en URLs que existen? Aquí tienes una solución simple y fiable. Primero resuelves el fallo; después lo dejas automatizado para que no vuelva a ocurrir. Aprenderás a crear un MU-plugin que repara los permalinks al detectar el problema y evita falsos positivos con caché o CDN.

Cuando en producción empiezan a aparecer 404 intermitentes en URLs que deberían existir, suele ser un problema de rewrite rules o configuración del servidor. En este artículo verás cómo detectar el fallo, repararlo automáticamente y reducir el impacto en usuarios, SEO y rendimiento de tu WordPress.

Un 404 en páginas que sí existen suele indicar que se han roto las reglas de reescritura (rewrite rules) de WordPress. Lo típico es entrar en Ajustes → Enlaces permanentes y guardar para “regenerar” los permalinks, pero el problema puede volver y pillarte fuera de horario, afectando ventas, SEO y la experiencia de usuario.

La solución práctica es automatizar la reparación: un MU-plugin vigila una URL centinela (una página pública que siempre debería responder 200/3xx) y, si detecta 404/410, ejecuta un flush de las rewrite rules con enfriamiento (p. ej., cada 3 horas como máximo). Así minimizas la caída y evitas estar pendiente del botón de “Guardar” cada vez que ocurre.

En Bubuku preferimos prevenir: monitorizar + reparar de forma controlada, mantiene la web sana mientras investigas la causa raíz (hosting, .htaccess o try_files, plugins de caché/seguridad…). El resultado: menos caídas, mejor UX y SEO.  

 ¿Por qué aparece el 404 por permalinks? (causas habituales)

El 404 en URLs que existen suele venir de reglas de reescritura desincronizadas: cambios en la estructura de enlaces permanentes, migraciones, activación/desactivación de plugins que registran CPT o despliegues que no regeneran reglas. Por eso “guardar” en Ajustes → Enlaces permanentes lo arregla solo temporalmente

La otra mitad del problema está en servidor: en Apache, un .htaccess ausente o sobrescrito; en Nginx, la falta de try_files $uri $uri/ /index.php?$args;. Si esa capa está mal, ni un flush dentro de WordPress lo soluciona hasta corregir la configuración. 

Factores que lo agravan: plugins de caché/seguridad que pisan reglas o sirven 404 cacheados, WP-Cron desactivado (retrasando tareas de mantenimiento) y entornos con cachés agresivas/CDN. Resultado: 404 intermitentes que aparecen “a deshoras” y generan avisos en Search Console.

Piensa en las rewrite rules como un mapa que WordPress necesita para traducir URLs bonitas en consultas a la base de datos. Si ese mapa se rompe, el navegador se pierde y devuelve un 404 aunque la página exista

Preparativos y requisitos previos

Antes de automatizar nada, conviene asegurarnos de que el terreno está bien preparado.

Si no lo haces, puedes encontrarte con falsos positivos (el sistema piensa que hay un error cuando en realidad no lo hay) o con que el flush no arregle nada.

Para que no te pierdas, lo he dividido en dos bloques:

  • Imprescindible → lo mínimo que debes revisar antes de instalar el MU-plugin.
  • Avanzado → ajustes que ayudan a evitar problemas más técnicos, pero que puedes revisar después.


Para que lo tengas más claro, aquí tienes el checklist dividido en dos niveles:

Checklist previo (Imprescindible)Qué mirar
Enlaces permanentesEvitar “Simple”. Usar estructura con slug (/%postname%/).
URL centinelaPágina pública y estable que siempre devuelva 200/3xx. Definir en wp-config.php.
CronAsegúrate de que WP-Cron está activo o configura un cron de sistema.
Checklist previo (Avanzado)Qué mirar
Caché/CDNTras un flush, purga caché o CDN para evitar falsos 404 cacheados.
ServidorRevisa .htaccess en Apache o try_files en Nginx. Sin eso, no hay permalinks que funcionen.
Trazas y logsActiva WP_DEBUG_LOG en pre-producción y consulta la opción bk_last_flush_rewrite para saber cuándo se ejecutó el último flush.

Solución automática con MU-plugin

La forma más fiable de cortar el problema de raíz es automatizar la regeneración de permalinks. La idea es sencilla: el sitio vigila una URL centinela (una página pública que siempre debería devolver 200/3xx) y, si en algún momento responde 404/410, ejecuta flush_rewrite_rules() con un enfriamiento para evitar bucles. Así el error se corrige solo y reduces al mínimo el tiempo “roto”.

Para que sea transparente en el día a día, lo convertimos en MU-plugin (se carga siempre, sin depender de activaciones manuales) y lo programamos con WP-Cron. Antes de colocarlo, define tu centinela en wp-config.php —por ejemplo la página de servicios— con: define('PREFIX_PG_CHECK_URL', 'https://tu-dominio.com/servicios/');

Con eso, crea el archivo wp-content/mu-plugins/prefix-auto-flush-rewrite.php y pega el siguiente código. Está comentado para que puedas ver de un vistazo qué hace cada parte (incluye fallback de HEAD a GET, cooldown, hook para purgar caché/CDN y dos atajos WP-CLI por si quieres comprobar o forzar el flush puntualmente).

<?php
/**
 * Plugin Name: PREFIX – Auto-fix 404 por permalinks
 * Description: Vigila una URL centinela y, si devuelve 404/410, hace flush de rewrite rules con enfriamiento.
 * Author: Tu nombre
 * Version: 1.0.0
 */
if (!defined('ABSPATH')) exit;
const PREFIX_OPTION_LAST_FLUSH = 'prefix_last_flush_rewrite';
/**
 * Programa una comprobación periódica (por defecto, cada hora).
 */
add_action('init', function () {
  if (!wp_next_scheduled('prefix_check_permalinks_event')) {
    wp_schedule_event(time() + 300, 'hourly', 'prefix_check_permalinks_event');
  }
});
add_action('prefix_check_permalinks_event', 'prefix_check_permalinks_and_fix');
/** Devuelve la URL centinela (constante o, si falta, la home). */
function prefix_get_sentinel_url() {
  $url = defined('PREFIX_PG_CHECK_URL') ? PREFIX_PG_CHECK_URL : home_url('/');
  return esc_url_raw($url);
}
/**
 * Comprueba el estado de la URL y repara si hace falta.
 * - Ignora sitios con estructura "Simple" (no hay permalinks que regenerar).
 * - Respeta un cooldown para evitar flush repetidos.
 */
function prefix_check_permalinks_and_fix() {
  $structure = get_option('permalink_structure');
  if (empty($structure)) return; // Estructura "Simple": sin acción.
  $cooldown = apply_filters('prefix_permalinks_cooldown', 3 * HOUR_IN_SECONDS);
  $last     = (int) get_option(PREFIX_OPTION_LAST_FLUSH, 0);
  if ($last && (time() - $last) < $cooldown) return; // Aún en enfriamiento.
  $url  = prefix_get_sentinel_url();
  $code = prefix_head_then_get_status($url);
  // Repara solo ante 404/410 reales.
  if ($code === 404 || $code === 410) {
    flush_rewrite_rules(true);                      // true => reescribe .htaccess si procede (Apache)
    update_option(PREFIX_OPTION_LAST_FLUSH, time(), false);
    /**
     * Hook para purgar caché/CDN o registrar métricas.
     * Ejemplo:
     * add_action('prefix_after_flush_rewrite', function($url, $code){ /* purga tu caché aquí */ /* });
     */
    do_action('prefix_after_flush_rewrite', $url, $code);
  }
}
/** Intenta HEAD; si el servidor lo bloquea (405/501), cae a GET. */
function prefix_head_then_get_status($url) {
  $resp = wp_remote_head($url, ['timeout' => 5, 'redirection' => 3]);
  if (is_wp_error($resp)) return null;
  $code = (int) wp_remote_retrieve_response_code($resp);
  if ($code === 405 || $code === 501 || $code === 0) {
    $resp = wp_remote_get($url, ['timeout' => 5, 'redirection' => 3]);
    if (is_wp_error($resp)) return null;
    $code = (int) wp_remote_retrieve_response_code($resp);
  }
  return $code;
}
/**
 * Atajos WP-CLI (opcionales):
 * - wp prefix-permalinks:check  -> muestra el código de la URL centinela
 * - wp prefix-permalinks:flush  -> fuerza un flush inmediato
 */
if (defined('WP_CLI') && WP_CLI) {
  WP_CLI::add_command('prefix-permalinks:check', function () {
    $url  = prefix_get_sentinel_url();
    $code = prefix_head_then_get_status($url);
    WP_CLI::line("URL: $url");
    WP_CLI::success("Código devuelto: " . var_export($code, true));
  });
  WP_CLI::add_command('prefix-permalinks:flush', function () {
    flush_rewrite_rules(true);
    update_option(PREFIX_OPTION_LAST_FLUSH, time(), false);
    WP_CLI::success('Flush ejecutado correctamente.');
  });
}


En la práctica, no tienes que tocarlo tras instalarlo: se ejecuta en segundo plano y solo actúa cuando detecta un 404 real en tu centinela. Si trabajas con caché/CDN, engancha la purga en el hook prefix_after_flush_rewrite para evitar que un 404 cacheado siga dando guerra. Y si alguna vez quieres intervenir, ahí tienes los dos comandos WP-CLI.

¿Qué significa el “cooldown” o enfriamiento?

Cuando el plugin detecta un 404 en la URL centinela, ejecuta un flush para regenerar los permalinks.

El problema es que no queremos que lo repita sin parar, porque podría sobrecargar el servidor.

Para evitarlo, se usa un sistema de cooldown (o “enfriamiento”): básicamente, un tiempo de espera mínimo entre reparaciones.

Ejemplo práctico:

  • A las 10:00 tu centinela devuelve 404 → el plugin hace flush y repara.
  • A las 10:05 vuelve a dar 404 → el plugin no actúa todavía, porque está en periodo de enfriamiento (3 horas por defecto).
  • A las 13:05 el enfriamiento termina. Si vuelve a haber 404, entonces sí ejecuta un nuevo flush.

De esta forma, evitas que el sistema entre en un bucle de reparaciones constantes y, al mismo tiempo, garantizas que la web no esté caída más de unas horas.

Idea para mejorar el plugin: puedes añadir una notificación por email cuando se ejecute el flush. Así te enteras de que hubo una caída y se reparó sola. En este artículo te explicamos cómo montar un sistema sencillo de verificación por correo en WordPress: Configurar verificación por email en la activación de cuenta.

Pasos rápidos para ponerlo en marcha

Ahora que ya tienes el MU-plugin preparado, lo más práctico es seguir un pequeño checklist de instalación.

Con estos pasos te aseguras de que la solución quede funcionando desde el primer momento sin complicaciones.

  1. Define la URL centinela. En tu archivo wp-config.php añade: define('PREFIX_PG_CHECK_URL', 'https://tu-dominio.com/servicios/'); Escoge una página pública y estable que siempre deba devolver 200/3xx.
  2. Copia el MU-plugin. Guarda el archivo en wp-content/mu-plugins/prefix-auto-flush-rewrite.php. (Si no existe la carpeta mu-plugins, créala primero).
  3. Verifica el cron. Asegúrate de que WP-Cron está activo. Si tu hosting lo limita, configura un cron de sistema o usa WP-CLI para lanzar eventos manualmente.
  4. Prueba y observa.
    • Visita tu URL centinela o espera al primer disparo del cron.
    • Revisa que exista la opción prefix_last_flush_rewrite en la base de datos: indica cuándo fue el último flush.
  5. Purga caché/CDN. Después del primer flush, recuerda vaciar la caché de tu plugin o la CDN. Así evitas servir 404 cacheados aunque la web ya esté reparada.

Recuerda: esto es una solución preventiva

El MU-plugin automatiza la reparación y te evita entrar a Ajustes → Enlaces permanentes cada vez que aparecen los 404.

Pero no olvides que este flush automático es solo una medida preventiva:

  • Si el error viene de un .htaccess roto (Apache) o de un bloque try_files incompleto (Nginx), seguirá ocurriendo hasta que ajustes el servidor.
  • El plugin mantiene la web en pie y reduce el tiempo de caída, pero la causa raíz debes investigarla y corregirla.

Piensa en este MU-plugin como un parche en una rueda pinchada: te permite seguir pedaleando sin quedarte tirado, pero no arregla el pinchazo de fondo. Igual que un seguro, te protege en el día a día, pero no sustituye el mantenimiento real del servidor o del hosting.

Alternativas manuales y con WP-CLI

Si prefieres no automatizar (o necesitas actuar ya), tienes dos caminos: manual desde el panel o comandos WP-CLI. Úsalos también como plan B si el MU-plugin aún no está en producción.

Desde el panel (rápido y sin terminal)

  1. Ve a Ajustes → Enlaces permanentes y pulsa Guardar cambios (no cambies nada).
  2. Si sigues con 404, revisa caché/CDN (purga) y la capa de servidor (Apache/Nginx) de abajo.

Con WP-CLI (ideal para CI/CD y servidores)

  • Forzar flush inmediato (reescribe .htaccess si procede): wp rewrite flush --hard
  • Ejecutar la comprobación del MU-plugin ahora (sin esperar al cron): wp cron event run prefix_check_permalinks_event
  • Ver el estado de la URL centinela (comando del MU-plugin): wp prefix-permalinks:check
  • Forzar el flush vía comando del MU-plugin (marca la hora interna también): wp prefix-permalinks:flush
  • Consultar la marca de tiempo del último flush: wp option get prefix_last_flush_rewrite

Servidor (cuando el flush no basta)

Apache (.htaccess) – asegúrate de tener el bloque estándar de WordPress (o dale permisos para reescribirlo):

# 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

Nginx – dentro de location / incluye try_files para el routing “bonito”:

location / {
    try_files $uri $uri/ /index.php?$args;
}


Guía de actuación rápida: usa esta tabla cuando aparezca un 404 “sin sentido”. Relaciona el síntoma con la acción inmediata para restaurar los permalinks, probar el MU-plugin o descartar problemas de caché/servidor. Es una referencia de emergencia para no perder tiempo.

SituaciónAcción inmediata
404 en URLs que existenGuardar enlaces permanentes o wp rewrite flush --hard
Necesito probar ya el MU-pluginwp cron event run prefix_check_permalinks_event
Quiero verificar la centinelawp prefix-permalinks:check
Flush no arregla el 404Purgar caché/CDN y revisar .htaccess / try_files

Errores comunes y cómo solucionarlos

Antes de entrar al detalle, usa este listado como una guía rápida de diagnóstico. Cada punto describe el fallo típico que provoca 404 “fantasma” y la acción inmediata para resolverlo sin perder tiempo. Si algo no encaja con tu caso, pasa al siguiente ítem y descártalo.

  • Falsos 404 por caché/CDN. Tras el flush, la CDN sigue sirviendo la versión rota.
    Solución: purga al terminar usando el hook prefix_after_flush_rewrite (conecta tu plugin de caché/CDN ahí).
  • URL centinela mal elegida. Página con A/B testing, bloqueos por rol o redirecciones temporales.
    Solución: usa una página pública y estable (p. ej., /servicios/). Evita landings con experimentos o cookies de geo/idioma.
  • El hosting bloquea HEAD o peticiones salientes. wp_remote_head() devuelve 405/501 o WP_Error (firewall o WP_HTTP_BLOCK_EXTERNAL).
    Solución: ya hay fallback a GET. Si el servidor bloquea todo, permite el dominio en WP_ACCESSIBLE_HOSTS o usa un cron del sistema + wp rewrite flush –hard como respaldo.
  • Cooldown demasiado largo/corto. O no actúa cuando debe, o hace flush con demasiada frecuencia.
    Solución: ajusta con el filter prefix_permalinks_cooldown (ej.: 1–3 horas suele ir bien).
  • WP-Cron no corre. Sitios con poco tráfico o proveedores que lo limitan.
    Solución: añade un cron de sistema (curl a wp-cron.php) o dispara manualmente: wp cron event run prefix_check_permalinks_event.
  • Estructura de enlaces “Simple”. No hay permalinks que regenerar, el MU-plugin se queda inactivo.
    Solución: activa una estructura con slug (/%postname%/ u otra equivalente).
  • Problema real de servidor. .htaccess ausente/ilegible (Apache) o try_files faltante (Nginx).
    Solución: restablece el bloque estándar de WordPress en .htaccess o añade try_files $uri $uri/ /index.php?$args; en location /.
  • Multisite mal planteado. Instalas el MU-plugin pero defines una centinela no válida para todos los sitios.
    Solución: define PREFIX_PG_CHECK_URL por sitio (por ejemplo en wp-config.php por dominio/env) o crea una opción por site y modifica prefix_get_sentinel_url() para leerla.
  • Desfase entre siteurl y la centinela. Diferencias http/https o www vs. raíz que generan cadenas de redirecciones.
    Solución: usa la URL canónica del sitio para PREFIX_PG_CHECK_URL y alinea home_url()/site_url().

Mantén tus permalinks bajo control sin preocupaciones

Con este MU-plugin, tu sitio WordPress se autocorrige solo cuando aparecen 404 por permalinks, reduciendo tiempos de caída y evitando tener que regenerar enlaces manualmente.

Es una solución preventiva y práctica, ideal para asegurar la experiencia de usuario y no perder visitas ni SEO por un fallo puntual.

Recuerda que la clave está en vigilar la causa raíz (servidor, caché, plugins). El plugin actúa como un seguro extra, pero el mantenimiento real lo marcas tú.

Si quieres reforzar la estabilidad de tu web o necesitas ayuda con desarrollos a medida, en Bubuku te podemos echar una mano. Échale un vistazo a nuestro servicio de mantenimiento WordPress.

Flujo de decisión para solucionar el problema 

Para que lo tengas de un vistazo, este diagrama muestra el proceso de detección y reparación con un rombo de decisión (¿devuelve 404?). Si no hay 404, seguimos monitorizando; si lo hay, se ejecuta el flush y, opcionalmente, la purga de caché.

Error 404 en WordPress por permalinks: preguntas y respuestas clave

Cuando aparece un 404 en URLs que existen, suele haber un problema con los enlaces permanentes o la capa de servidor/caché. Esta sección reúne respuestas breves y accionables a las dudas más habituales para que puedas diagnosticar y arreglar el fallo sin perder tiempo.

Sí, si lo limitas a 404/410 reales y lo aplicas por ejemplo cada 3 h. Así evitas bucles o gasto innecesario.

Prácticamente, nada: la comprobación usa HEAD (y fallback a GET) y el flush ocurre muy de vez en cuando por el cooldown.

Sí. El flush actualiza reglas internas de WordPress. Si .htaccess (Apache) o try_files (Nginx) están mal, corrígelos para que el enrutado funcione.

Usa un cron del sistema para ejecutar eventos con wp cron event run –due-now o lanza directamente wp rewrite flush –hard. También puedes ejecutar solo prefix_check_permalinks_event.

Dos opciones:

  • Nativo: wp rewrite flush –hard.
  • Del MU-plugin: wp prefix-permalinks:flush y wp prefix-permalinks:check para ver el código de la centinela.

Purgar caché/CDN (para evitar 404 cacheados) y revisar servidor: restablece el bloque estándar de .htaccess o añade try_files $uri $uri/ /index.php?$args; en Nginx.

Pueden generar soft-404 y mala UX. Lo clave es reducir el tiempo de caída: automatiza la reparación y estabiliza rastreo e indexación.


Si prefieres que alguien lo revise contigo, podemos acompañarte paso a paso hasta que quede estable y sin 404. Aquí tienes nuestro servicio de mantenimiento WordPress.

Resumen de privacidad

Esta web utiliza cookies para que podamos ofrecerte la mejor experiencia de usuario posible. La información de las cookies se almacena en tu navegador y realiza funciones tales como reconocerte cuando vuelves a nuestra web o ayudar a nuestro equipo a comprender qué secciones de la web encuentras más interesantes y útiles.

Cookies estrictamente necesarias

Las cookies estrictamente necesarias tiene que activarse siempre para que podamos guardar tus preferencias de ajustes de cookies.

Cookies de terceros

Esta web utiliza Google Analytics para recopilar información anónima tal como el número de visitantes del sitio, o las páginas más populares.

Dejar esta cookie activa nos permite mejorar nuestra web.