WordPin investigando un error 500 en WordPress provocado por una modificación en el archivo functions.php

El error 500 en WordPress que no dejaba rastro · WordPin 015

🎧 Escuchar: El error 500 en WordPress que no dejaba rastro · WordPin 015

La web llevaba meses funcionando sin incidencias. Era el sitio corporativo de una agencia de marketing: páginas de servicios, blog activo, formularios de contacto y algún módulo personalizado en el tema hijo. Nada especialmente complejo. El equipo había añadido funcionalidades propias a través del functions.php del tema hijo a lo largo del tiempo, en pequeños incrementos. Era un archivo con historial.

La mañana en que llegó el aviso, alguien había hecho una modificación en ese archivo. Una pequeña adición, según dijeron: registrar un nuevo tipo de menú. Cuatro líneas. Nada que no se hubiera hecho antes. Pero el sitio respondía con un error 500 en WordPress en cualquier URL que se intentara cargar. Página de inicio, entradas, administración, archivo. Todo igual: pantalla en blanco o mensaje genérico de error interno del servidor. Sin detalle, sin indicación, sin nada que señalara dónde mirar.

Lo primero que hicieron fue intentar revertir el cambio desde el editor del tema. Sin embargo, la operación no restauró correctamente el archivo y el bloque de la función terminó duplicado. El error seguía ahí. Eso no cuadraba. Si la modificación era la causa, deshacer debería haber bastado. Pero el sitio continuaba caído. Ahí fue cuando me pasaron el caso.

Sello del archivo 015 de WordPin marcado como abierto
Ficha del archivo Nº: 015

Operario: WordPin

Archivo del caso: El error 500 en WordPress que no dejaba rastro

Empresa o negocio: Web de una agencia de marketing

Archivado en: Errores en WordPress

Nivel: Intermedio

Cuando un error 500 en WordPress no deja nada en pantalla

El síntoma era claro en la superficie: HTTP 500 en todas las URL del sitio, sin excepción. Eso descartaba de entrada un fallo puntual en una plantilla concreta o un problema con una entrada específica. El fallo era anterior en la cadena de carga. WordPress ni siquiera llegaba a intentar renderizar contenido.

Lo primero que comprobé fue el estado de los plugins. Un error 500 en WordPress que afecta al sitio completo, incluyendo el área de administración, suele tener su origen antes de que WordPress termine de inicializarse. Los plugins cargan después del core y antes del tema, pero si el fallo ocurre en la fase de carga del tema, ningún plugin activo sería el responsable directo. Aun así, valía la pena descartar.

Accedí al servidor por FTP, renombré la carpeta de plugins completa y probé de nuevo. El error persistía. No era ningún plugin el origen inmediato de la caída. Primera hipótesis descartada, pero no del todo irrelevante: al menos confirmaba que el problema estaba por debajo o por encima en la cadena.

El error 500 en WordPress con los plugins fuera de juego

Con los plugins descartados, la segunda sospecha fue más tentadora. La agencia usaba un plugin de caché de página con integración en servidor. Llevaba activo desde hacía tiempo y había funcionado sin problemas, pero era el tipo de componente que podía estar sirviendo una respuesta cacheada corrupta. Si el archivo de caché se había generado justo durante el momento del fallo, el sitio estaría devolviendo esa respuesta rota a todos los visitantes, independientemente del estado real de WordPress.

Tenía sentido. Era un escenario plausible. Purgué la caché desde el panel del hosting, borré manualmente los archivos de caché almacenados en /wp-content/cache/ y accedí al sitio añadiendo un parámetro en la URL para comprobar si el sistema de caché lo trataba como una petición independiente. El resultado fue el mismo. HTTP 500, sin cambios. Las medidas aplicadas no habían resuelto el error, así que la caché quedaba fuera del foco, aunque no por un razonamiento lógico sobre qué puede cachearse: simplemente, ninguna de las pruebas había alterado el comportamiento del sitio.

Eso dejaba el foco en el tema. Renombré la carpeta del tema hijo. El sitio seguía sin cargar. Renombré también la carpeta del tema padre, dejando a WordPress sin tema accesible. El resultado fue el mismo en todas las URLs. Eso reducía la probabilidad de que el fallo estuviera en las plantillas del tema. El siguiente paso lógico era mirar los logs para localizar el origen.

Activé WP_DEBUG añadiendo las constantes en wp-config.php:

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );

Recargué el sitio. Luego fui directamente al archivo debug.log generado en /wp-content/. Lo que encontré ahí cambió la dirección de todo.

Lo que los logs decían y el navegador no mostraba

El log registraba un fallo temprano, antes de que WordPress completara su inicialización. La línea era concisa:

[PHP Fatal error] Cannot redeclare function_name() (previously declared in
/wp-content/themes/tema-hijo/functions.php:47)
in /wp-content/themes/tema-hijo/functions.php on line 89

Una función declarada dos veces en el mismo archivo. Durante la reversión, habían añadido de nuevo el bloque al final del archivo sin eliminar la declaración original. El resultado: dos declaraciones del mismo nombre de función en el mismo archivo, lo que en PHP es un error fatal sin posibilidad de recuperación.

Pero al revisar el archivo directamente desde el servidor, aparecía algo más. Al abrir functions.php con un editor de código que mostraba caracteres no imprimibles, la primera línea del archivo tenía tres bytes antes de la etiqueta <?php. Un BOM (Byte Order Mark): una marca de codificación invisible que algunos editores insertan automáticamente en archivos guardados en UTF-8 con BOM. Esos tres bytes se interpretan como salida antes de que PHP ejecute ningún código. Y en WordPress, cualquier salida antes de que se envíen las cabeceras HTTP puede provocar que funciones como headers_sent() devuelvan true, provocando problemas en operaciones que necesitan enviar cabeceras HTTP, como iniciar sesiones, establecer cookies o realizar redirecciones.

El caso tenía dos capas: una función duplicada que generaba el error fatal visible en el log, y un carácter BOM que probablemente llevaba tiempo en el archivo sin provocar problemas evidentes. No era posible saber con certeza si el BOM había estado siempre ahí o si lo había introducido el editor del tema del propio WordPress al guardar, pero su presencia era un problema independiente del fallo de la función duplicada.

La prueba confirmada del fallo principal era la entrada en el log. La del BOM era la inspección directa del archivo con un editor que mostraba caracteres ocultos. Dos problemas distintos, descubiertos en el mismo archivo, con el mismo origen: ediciones sucesivas sin validación previa.

Un error fatal de PHP detiene la ejecución del script. El servidor devuelve HTTP 500 sin mostrar detalles al visitante. Sin los logs activos, no había nada más en lo que apoyarse para saber qué había ocurrido exactamente.

Limpiar el archivo sin introducir el siguiente problema

La solución parecía evidente desde el diagnóstico: eliminar la función duplicada y quitar el BOM. Pero hacer eso directamente en producción, desde el editor del propio WordPress o desde un gestor de archivos del hosting, era reproducir exactamente el mismo escenario que había generado el fallo. La edición apresurada en un entorno en directo, sin validación, sin copia previa.

Abrir el archivo sin repetir el mismo error

Descargué el archivo por FTP antes de tocarlo. Eso era lo primero. Con una copia local intacta del estado actual, cualquier intervención posterior tenía marcha atrás. A continuación abrí el archivo con un editor de código con soporte para detección de BOM y visualización de caracteres invisibles. La marca estaba ahí, al inicio del archivo, antes del <?php. La eliminé. Después localicé las dos declaraciones de la función duplicada y dejé solo la versión correcta, la original.

Antes de subir nada, validé la sintaxis del archivo con php -l desde línea de comandos:

php -l functions.php
No syntax errors detected in functions.php

Sin errores de sintaxis. El archivo estaba limpio. Subí la versión corregida por FTP, sobreescribiendo el archivo en producción. Recargué el sitio. Cargó sin problemas.

Después verifiqué el log de debug, que ya no registraba nuevas entradas de error. Comprobé el área de administración, las páginas internas, el blog y los formularios. Todo respondía. El error 500 en WordPress había desaparecido porque su causa principal había desaparecido: la función duplicada que generaba el error fatal estaba fuera del archivo.

La agencia preguntó si debían restaurar desde una copia de seguridad. Era una opción, pero no la más precisa. Una restauración completa habría revertido cualquier otro cambio legítimo hecho en el periodo cercano al fallo. La intervención quirúrgica sobre el archivo concreto era menos arriesgada y más controlada, siempre que la validación previa confirmara que el archivo era correcto antes de subirlo. Eso es exactamente lo que hizo que php -l fuera el paso que no podía saltarse.

Después de resolver el error 500 en WordPress, también revisé el estado del functions.php para identificar las modificaciones que se habían realizado directamente desde el área de administración. El editor de temas de WordPress guarda los cambios directamente en el archivo y no proporciona un historial convencional de versiones ni una copia de seguridad automática. Aunque incorpora comprobaciones para detectar errores fatales, no sustituye a una validación independiente del código. En un archivo con tanta responsabilidad como functions.php, cualquier edición descuidada sigue representando un riesgo real de producción.

Archivo de WordPin 015 marcado como completado

💡 Qué he aprendido

Este caso me confirmó algo que ya sospechaba pero que necesitaba ver de nuevo: un error 500 en WordPress sin mensaje visible no es un fallo opaco por naturaleza. Es opaco porque WP_DEBUG no está activo y los logs PHP no se están revisando. Cuando se encienden, el ruido desaparece y el fallo aparece con nombre y número de línea. La oscuridad era una cuestión de configuración, no del error en sí.

También aprendí a no fijarme solo en el cambio reciente. El BOM podía llevar tiempo en el archivo. No era el origen del error fatal, pero era un problema latente que convivía con el código sin que nadie lo hubiera detectado porque el editor del tema de WordPress no lo muestra. Eso me obliga a revisar no solo lo que se tocó, sino el estado completo del archivo. Un fallo nuevo puede estar acompañado de otro más antiguo que nadie vio porque no daba síntomas todavía.

Lo que cambió en mi forma de trabajar este tipo de caso: ahora descargo el archivo antes de cualquier intervención, valido con php -l antes de subir, y reviso siempre con un editor que muestre caracteres no imprimibles. No por protocolo, sino porque ya vi lo que pasa cuando no se hace.

Cuaderno de WordPin

Forense WordPress

Archivo Nº 015:: El error 500 en WordPress que no dejaba rastro

🧩 Notas técnicas

⬋⬋

La web corporativa de una agencia de marketing devolvía HTTP 500 en todas sus URLs tras una edición en el functions.php del tema hijo. El navegador no mostraba detalle y revertir el cambio desde el editor de temas no resolvió la caída.

El log de debug identificó la causa: una función declarada dos veces tras una edición mal revertida. Durante la inspección directa del archivo con un editor adecuado se detectó además un carácter BOM al inicio del archivo, anterior al <?php. Ambos problemas se corrigieron localmente, se validó la sintaxis y se subió el archivo por FTP.

🔎 Pistas detectadas

⬋⬋

  • El error afectaba a todas las URLs del sitio, incluida la administración, lo que descartaba un fallo puntual en plantilla o contenido.
  • Desactivar plugins y dejar los temas inaccesibles no resolvía el 500, lo que redujo el foco hacia el archivo que el log terminaría señalando.
  • El log de debug mostraba un PHP Fatal error: Cannot redeclare con número de línea exacto en functions.php.
  • La inspección del archivo con un editor adecuado reveló un BOM de tres bytes antes de la etiqueta <?php.
  • La reversión realizada desde el editor del tema de WordPress había dejado duplicado el bloque de función en lugar de eliminar la declaración original.

🚫 Errores en WordPress detectados

⬋⬋

  • Función PHP declarada dos veces: durante la reversión, añadieron el bloque al final del archivo sin eliminar la declaración original, provocando un fatal error que detenía la carga completa del sitio.
  • BOM en functions.php: tres bytes invisibles antes del <?php pueden generar salida antes de que WordPress gestione cabeceras, con el riesgo de interferir con redirecciones y sesiones según el contexto de ejecución.
  • WP_DEBUG desactivado en producción: sin log activo, el fallo era imposible de diagnosticar desde el navegador; el error quedaba completamente oculto para el equipo.
  • Edición directa de functions.php sin validación: el editor de temas integrado en WordPress no sustituye a una validación de sintaxis independiente antes de desplegar los cambios; aunque incorpora comprobaciones para detectar errores fatales, estas no equivalen a una validación completa del archivo.
  • Sin copia local antes de editar: la ausencia de respaldo del archivo antes de la intervención original limitó las opciones de recuperación rápida y obligó a reconstruir el estado correcto manualmente.

📘 Glosario de WordPress

⬋⬋

  • functions.php: archivo del tema que WordPress carga en cada petición para registrar funciones, hooks y personalizaciones; un error en él detiene toda la inicialización del sitio.
  • BOM (Byte Order Mark): marca de codificación de tres bytes que algunos editores insertan al inicio de archivos UTF-8; si esos bytes se emiten antes de las cabeceras HTTP, pueden provocar problemas con redirecciones y sesiones en PHP.
  • WP_DEBUG_LOG: constante de WordPress que permite registrar los errores PHP en un archivo de log, habitualmente wp-content/debug.log, cuando WP_DEBUG está activado. Se puede combinar con WP_DEBUG_DISPLAY en false para evitar que los errores se muestren en pantalla.
  • PHP Fatal error: error que impide que el script continúe ejecutándose normalmente; según el contexto y el manejo del error, puede provocar una respuesta HTTP 500 o una pantalla de error de WordPress.
  • php -l: comando de línea que verifica la sintaxis de un archivo PHP sin ejecutarlo; permite detectar errores antes de subir cambios a producción.

📏 Mini guía práctica

⬋⬋

  1. Activa WP_DEBUG y WP_DEBUG_LOG en wp-config.php preferentemente en un entorno de pruebas o staging; si es imprescindible hacerlo en producción, mantén WP_DEBUG_DISPLAY en false y protege el acceso al archivo debug.log.
  2. Descarga el archivo functions.php por FTP antes de modificarlo y guarda la copia en local como respaldo del estado previo a cualquier intervención.
  3. Abre el archivo con un editor de código que muestre caracteres invisibles y detecte BOM para identificar problemas de codificación no visibles en el editor del tema.
  4. Valida la sintaxis del archivo con php -l nombre-del-archivo.php en local o en el servidor antes de subir la versión corregida a producción.
  5. Revisa el archivo de log generado en /wp-content/debug.log para obtener el nombre del error, el archivo afectado y el número de línea exacto donde se produjo el fallo.

Comparte el conocimiento. Comparte la historia

Expedientes y Archivos

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Respetamos tu privacidad. Los datos que proporciones se utilizarán únicamente para gestionar y mostrar tu comentario, así como para prevenir el uso indebido o el spam. Puedes consultar más información en nuestra política de privacidad.

Subir