max_input_vars de WordPress: por qué se rompen menús y formularios, y cómo solucionarlo

¿Te fue útil?

Un día tu editor hace clic en Guardar menú. El spinner gira. La página se recarga. La mitad de los elementos del menú desaparecen en silencio como si nunca hubieran existido. O un formulario de pago extenso se envía, pero algunos campos vuelven en blanco, las validaciones no tienen sentido y tu bandeja de soporte arde.

Este es el tipo de fallo que hace que los equipos culpen a WordPress, al tema, al plugin, al CDN y a veces a la luna. En realidad, a menudo es un límite de seguridad de PHP haciendo su trabajo: max_input_vars. La solución es simple. El diagnóstico no lo es —a menos que sepas dónde mirar y qué medir.

Qué limita realmente max_input_vars (y por qué WordPress lo alcanza)

max_input_vars es una directiva de configuración de PHP que limita el número de variables de entrada aceptadas por solicitud. Las variables de entrada se rellenan típicamente desde:

  • Campos del cuerpo POST (envíos de formularios)
  • Parámetros de consulta GET
  • Cookies (sí, también estas)

En el administrador de WordPress, los principales responsables son menús de navegación gigantes, constructores de páginas complejos, estructuras de menús multilenguaje, editores de atributos de producto y grupos de campos personalizados que muestran muchos campos repetidos. Cada elemento de array anidado cuenta como una variable.

Así que cuando WordPress construye un POST del editor de menús que incluye cientos de campos menu-item-*, PHP parsea felizmente hasta que choca con el techo —luego se detiene. WordPress recibe un conjunto de datos truncado y “guarda” fielmente esa realidad truncada. Por eso la interfaz puede parecer que tuvo éxito mientras los datos acaban faltando.

Datos interesantes y contexto histórico (porque este problema tiene una historia)

  1. PHP no siempre tuvo max_input_vars; se hizo común como mitigación contra colisiones de tablas hash y abusos tipo inyección de variables que podían consumir CPU y memoria al parsear peticiones enormes.
  2. El valor por defecto suele ser 1000 en muchas distribuciones, pero los paneles de hosting y las compilaciones “endurecidas” frecuentemente lo fijan más bajo sin avisarte.
  3. Antes de que max_input_vars fuera ampliamente conocido, la gente culpaba a WordPress por “eliminar aleatoriamente” elementos de menú —porque el fallo es silencioso salvo que mires los logs.
  4. PHP cuenta las entradas anidadas individualmente: acf[field_1][sub][0][name] no es “una cosa”; son múltiples variables cuando se aplana en la tabla de símbolos interna.
  5. Los navegadores no imponen este límite. El cliente envía todo; el servidor descarta el resto. Esa asimetría es por qué parece un bug fantasma.
  6. Algunos entornos antiguos usaban Suhosin (un parche/extensión de endurecimiento) que introdujo sus propios límites como suhosin.post.max_vars; algunos hosts legacy a veces mantienen esas restricciones.
  7. Los menús de WordPress pueden explotar el conteo de entradas porque cada elemento del menú no es un solo campo; es un paquete (título, URL, clases, target, XFN, posición, padre, etc.).
  8. Los grandes cargas de cookies (marketing, pruebas A/B, herramientas de consentimiento) también pueden consumir el presupuesto de input-vars, porque las cookies también se parsean como variables.
  9. HTTP/2 y stacks modernos hicieron más fiable el transporte de solicitudes administrativas grandes, lo que irónicamente aumenta la frecuencia con la que golpeas límites de parseo del servidor en lugar de timeouts de red.

Verdad operativa: límites como max_input_vars no son “bugs”. Son disyuntores. Pero si el disyuntor es demasiado pequeño para tu carga, obtienes apagones parciales.

Una idea parafraseada: “La esperanza no es una estrategia”. En este caso: no esperes que el menú se guarde. Mide el tamaño de la solicitud y configura en consecuencia.

Cómo se manifiesta en la interfaz: fallos reales, no teoría

Aquí están los patrones que veo en flotas WordPress en producción, donde “el sitio parece bien” hasta que un editor intenta cambiar algo.

Menús

  • Síntoma: Añades elementos al menú, haces clic en “Guardar menú” y algunos elementos desaparecen o vuelven a su estado anterior.
  • Por qué: WordPress publica una lista masiva de campos menu-item. PHP parsea solo las primeras N variables, y la cola nunca llega a WordPress.
  • Se nota cuando: Peor al reordenar, añadir muchos elementos a la vez o tener mega-menús con muchos niveles anidados.

Constructores de páginas y campos personalizados

  • Síntoma: Las páginas de Elementor/ACF/WPBakery se guardan, pero algunos bloques se restablecen, los repeaters pierden filas o subcampos “aleatorios” quedan en blanco.
  • Por qué: Los repetidores y estructuras anidadas explotan en miles de variables.
  • Se nota cuando: Ediciones pequeñas se guardan bien; ediciones grandes corrompen solo partes de los datos.

Formularios

  • Síntoma: Formularios complejos se envían pero llegan con campos faltantes, o las validaciones fallan en campos que el usuario realmente llenó.
  • Por qué: PHP descarta variables más allá del límite; el plugin ve claves ausentes y las trata como vacías.
  • Se nota cuando: Correlaciona con formularios que tienen secciones repetibles, asistentes multi‑paso o muchos campos ocultos.

Ediciones de productos WooCommerce

  • Síntoma: Atributos de producto, variaciones o metadatos “no se quedan”.
  • Por qué: Las variaciones pueden generar un número verdaderamente absurdo de input vars por guardado.
  • Se nota cuando: Los productos simples están bien; los productos variables están malditos.

Broma corta #1: El formulario no olvidó tus datos. PHP simplemente decidió que ya había visto suficiente por hoy.

Guía rápida de diagnóstico

Este es el orden que encuentra el cuello de botella rápidamente sin deambular por el administrador de WordPress como un turista perdido.

Primero: confirma que el síntoma es truncamiento de la solicitud, no permisos o caché

  • Reproduce el guardado en un solo navegador, con sesión de administrador.
  • Revisa los logs del servidor en busca de una advertencia de PHP sobre max_input_vars.
  • Comprueba si solo falta la “cola” de un gran conjunto de datos (patrón clásico de truncamiento).

Segundo: identifica qué SAPI de PHP maneja wp-admin

  • ¿Nginx con PHP-FPM? ¿Apache con php-fpm? ¿Apache con mod_php? ¿Contenedor con un ini personalizado?
  • No adivines. Confirma usando una consulta por línea de comandos o un phpinfo controlado limitado solo a administradores.

Tercero: verifica la configuración activa y quién la está sobrescribiendo

  • Inspecciona php -i y los ajustes del pool FPM relevantes.
  • Busca sobrescrituras por directorio (.user.ini, .htaccess), paneles, o fragmentos en conf.d.
  • Luego haz un cambio en un solo lugar y recarga el servicio correcto.

Cuarto: evalúa límites adyacentes

  • post_max_size y upload_max_filesize (límites de tamaño)
  • max_input_time (tiempo de parseo)
  • Terminación de petición FPM (request_terminate_timeout)
  • Limites de body en Nginx/Apache (client_max_body_size, LimitRequestBody)

Si sigues ese orden, por lo general tendrás una causa raíz en 10–20 minutos. Si no, “lo arreglarás” subiendo todo al 11 y luego te preguntarás por qué el uso de memoria parece obra de un minero de criptomonedas.

Cómo PHP cuenta las “variables de entrada” (la parte que todo el mundo entiende mal)

La gente lee max_input_vars=1000 y piensa “mi formulario tiene 200 campos, estoy a salvo”. Luego despliegan un campo repetible y todo se rompe.

El parseo de entradas de PHP convierte los parámetros entrantes en pares clave/valor dentro de superglobales como $_POST. Cuando envías estructuras anidadas (común en WordPress), PHP las expande. Ejemplo:

  • menu-item[123][title]=Home
  • menu-item[123][url]=/
  • menu-item[123][classes]=top

Esas son tres variables, no “un elemento de menú”. Ahora multiplícalo por cientos de elementos y docenas de propiedades. Llegas a 1000 más rápido de lo que nadie espera.

Además: las cookies cuentan. Muchas herramientas de personalización y analítica pueden añadir cookies grandes. Incluso si tu POST administrativo está cerca del límite, unas pocas cookies pueden hacerlo superar. No es la causa más común, pero cuando ocurre se siente especialmente injusto.

Finalmente: el truncamiento no siempre es “eliminar los últimos ítems que añadiste”. Es “eliminar las variables que vienen después del umbral en el orden de parseo”. El orden de parseo es aproximadamente el orden en que aparecen los campos en el cuerpo codificado de la solicitud. Si tu plugin cambia el orden de campos, las “piezas faltantes” pueden parecer aleatorias.

Broma corta #2: max_input_vars es como un límite de reuniones de oficina: después de 1000 entradas, nadie escucha de todos modos.

Dónde establecerlo: Apache, Nginx+PHP-FPM, cPanel, contenedores

Regla de oro: cambia la configuración donde el runtime la lee

Hay muchas maneras de “ajustar” valores de PHP. Solo algunas aplican al camino real de tu solicitud. Si ejecutas Nginx + PHP-FPM, editar el php.ini de Apache no hace nada salvo darte falsa confianza.

Nginx + PHP-FPM (lo más común en VPS modernos)

Lugares típicos:

  • /etc/php/8.x/fpm/php.ini
  • /etc/php/8.x/fpm/conf.d/*.ini
  • Archivo del pool FPM: /etc/php/8.x/fpm/pool.d/www.conf (puede sobrescribir vía php_admin_value)

Tras los cambios: recarga php8.x-fpm. Recargar solo Nginx no aplicará cambios del ini de PHP.

Apache con PHP-FPM

Se aplican las mismas reglas de PHP-FPM. Apache solo es un proxy inverso hacia FPM. Aún necesitas recargar FPM. Recargar Apache es opcional a menos que cambies la configuración del proxy.

Apache con mod_php (menos común ahora)

Los ajustes suelen venir del php.ini cargado por Apache y archivos adicionales conf.d. Los cambios requieren recarga/reinicio de Apache.

Hosting compartido / cPanel / Plesk

A menudo usan ajustes ini por usuario a través del panel o .user.ini. Pero ten cuidado: la UI del panel puede estar escribiendo en un ini mientras el PHP en ejecución lee otro (diferentes versiones de PHP, diferente handler). Confirma con una consulta en tiempo de ejecución.

Contenedores (Docker, Kubernetes)

O incorporas el ini en la imagen o montas un archivo de configuración. La mayor trampa: editar un archivo en un contenedor en ejecución y perderlo en el siguiente despliegue. Si no está en Git o en el manifiesto de despliegue, no existe.

¿Qué número debes poner?

Valores comunes que funcionan:

  • 3000 para “WordPress más grande que la media” (menús más grandes, algunos repeaters de ACF)
  • 5000–10000 para edición intensiva de variaciones de WooCommerce, menús multilingüe o constructores usados como hojas de cálculo

No soy alérgico a números altos, pero sí a fijarlos altos sin salvaguardas. Si subes input vars, considera también los límites de tamaño de petición y reglas WAF, y monitoriza memoria y tiempos de PHP-FPM. Hazlo seguro, no solo permisivo.

Tareas prácticas (comandos, salidas y decisiones)

Estas son las tareas “haz esto, ve eso, decide esto” que uso cuando estoy de guardia y el menú de alguien se está comiendo a sí mismo.

Tarea 1: Comprobar la configuración de PHP CLI (línea base rápida)

cr0x@server:~$ php -i | grep -i max_input_vars
max_input_vars => 1000 => 1000

Qué significa: PHP CLI está configurado actualmente en 1000. Esto puede o no coincidir con el runtime web (FPM vs CLI pueden diferir).

Decisión: Si el CLI es bajo, es una pista de que los valores por defecto de la distro son bajos. Aún confirma el SAPI web después.

Tarea 2: Identificar el servicio PHP-FPM en ejecución y la versión

cr0x@server:~$ systemctl list-units --type=service | grep -E 'php.*fpm'
php8.2-fpm.service                 loaded active running   The PHP 8.2 FastCGI Process Manager

Qué significa: PHP-FPM 8.2 está en ejecución.

Decisión: Cualquier cambio de configuración debe aplicarse a las rutas de configuración de FPM para PHP 8.2, y debes recargar ese servicio.

Tarea 3: Preguntar a PHP-FPM qué archivo ini usa (vía php-fpm -i)

cr0x@server:~$ php-fpm8.2 -i | grep -E 'Loaded Configuration|Scan this dir'
Loaded Configuration File => /etc/php/8.2/fpm/php.ini
Scan this dir for additional .ini files => /etc/php/8.2/fpm/conf.d

Qué significa: Esta es la ubicación autorizada para el ini de FPM. Los fragmentos conf.d pueden sobrescribir valores.

Decisión: Edita /etc/php/8.2/fpm/php.ini o añade un archivo dedicado en conf.d (preferible para gestión).

Tarea 4: Comprobar max_input_vars en el contexto de FPM

cr0x@server:~$ php-fpm8.2 -i | grep -i max_input_vars
max_input_vars => 1000 => 1000

Qué significa: El runtime web también está en 1000 (al menos desde la perspectiva de FPM).

Decisión: Subirlo está justificado si tu solicitud del administrador de WordPress necesita más de 1000 variables.

Tarea 5: Buscar sobrescrituras en los configs del pool FPM

cr0x@server:~$ grep -R --line-number -E 'max_input_vars|php_(admin_)?value' /etc/php/8.2/fpm/pool.d
/etc/php/8.2/fpm/pool.d/www.conf:315:;php_admin_value[max_input_vars] = 1000

Qué significa: Hay una sobrescritura comentada. Si estuviera habilitada, forzaría el valor para ese pool.

Decisión: Elige un único plano de control: o lo fijas globalmente en php.ini/conf.d o lo fuerzas en el pool con php_admin_value. No lo dividas.

Tarea 6: Añadir un archivo conf.d dedicado para claridad

cr0x@server:~$ sudo tee /etc/php/8.2/fpm/conf.d/99-wordpress-input-vars.ini >/dev/null <<'EOF'
; WordPress admin can exceed default input var count (menus, ACF, Woo variations).
max_input_vars = 5000
EOF

Qué significa: Has añadido un fragmento de configuración de alta precedencia (99-*) para fijar el valor para FPM.

Decisión: 5000 es un punto de partida razonable para menús grandes. Si editas rutinariamente miles de variaciones, considera valores mayores —tras medir.

Tarea 7: Recargar PHP-FPM y verificar que lo cargó realmente

cr0x@server:~$ sudo systemctl reload php8.2-fpm
cr0x@server:~$ php-fpm8.2 -i | grep -i max_input_vars
max_input_vars => 5000 => 5000

Qué significa: FPM tiene el nuevo valor.

Decisión: Ahora reproduce el guardado en WordPress. Si todavía falla, probablemente estés golpeando otro límite (tamaño del body, timeouts o lógica de la aplicación).

Tarea 8: Revisar logs de PHP en busca del mensaje revelador

cr0x@server:~$ sudo tail -n 50 /var/log/php8.2-fpm.log
[27-Dec-2025 11:09:31] WARNING: [pool www] child 18422 said into stderr: "PHP Warning:  Unknown: Input variables exceeded 1000. To increase the limit change max_input_vars in php.ini in Unknown on line 0"

Qué significa: Advertencia clásica: PHP alcanzó el límite y truncó el parseo de entradas.

Decisión: Si ves esto en el momento del guardado en el admin, puedes dejar de debatir. Sube el límite (y confirma que no hay otras restricciones).

Tarea 9: Comprobar límites de tamaño de body en Nginx (problema común asociado)

cr0x@server:~$ sudo nginx -T 2>/dev/null | grep -R --line-number 'client_max_body_size' /etc/nginx
/etc/nginx/nginx.conf:36:    client_max_body_size 10m;

Qué significa: Nginx rechazará cuerpos mayores de 10 MB (con un 413).

Decisión: Si los administradores están subiendo payloads serializados enormes de constructores o ediciones de variaciones de producto, puede que necesites subir esto también. Si no ves 413s, no lo toques.

Tarea 10: Confirmar límites de body en Apache si Apache está en juego

cr0x@server:~$ sudo apachectl -M | head
Loaded Modules:
 core_module (static)
 so_module (static)
 watchdog_module (static)
 http_module (static)

Qué significa: La lista de módulos confirma que Apache está instalado y qué está cargado (este fragmento no muestra aún el handler de PHP).

Decisión: Si Apache está delante del sitio, busca en las configuraciones LimitRequestBody cuando veas problemas 413/400.

Tarea 11: Encontrar qué handler PHP usa Apache (mod_php vs proxy_fcgi)

cr0x@server:~$ sudo apachectl -M | grep -E 'php|proxy_fcgi'
 proxy_fcgi_module (shared)

Qué significa: Apache está usando proxy FastCGI, usualmente hacia PHP-FPM.

Decisión: Los cambios deben hacerse en PHP-FPM, no en el php.ini de Apache (a menos que también uses mod_php, que no es el caso aquí).

Tarea 12: Validar la ruta activa de php.ini y sobrescrituras mediante un endpoint temporal solo para administradores

cr0x@server:~$ sudo -u www-data php -r 'echo "SAPI=".php_sapi_name().PHP_EOL; echo "max_input_vars=".ini_get("max_input_vars").PHP_EOL;'
SAPI=cli
max_input_vars=1000

Qué significa: Esto todavía muestra valores del CLI, no del web. Recordatorio útil: el contexto importa.

Decisión: Si no puedes exponer phpinfo de forma segura, prefiere inspeccionar FPM directamente (php-fpm8.2 -i) y revisar logs. Evita dejar endpoints de diagnóstico por ahí.

Tarea 13: Confirmar que WordPress recibe el POST truncado contando claves en una prueba controlada

cr0x@server:~$ sudo tee /var/www/html/wp-content/mu-plugins/input-vars-debug.php >/dev/null <<'EOF'

Qué significa: Un plugin must-use que imprime conteos para administradores cuando añades ?input_vars_debug=1 en wp-admin. Esto ayuda a probar el truncamiento sin adivinar.

Decisión: Úsalo brevemente y luego elimínalo. Los plugins de depuración son como escaleras: útiles hasta que alguien tropieza con ellas.

Tarea 14: Vigilar PHP-FPM por impacto en recursos tras aumentar el límite

cr0x@server:~$ sudo systemctl status php8.2-fpm --no-pager | sed -n '1,15p'
● php8.2-fpm.service - The PHP 8.2 FastCGI Process Manager
     Loaded: loaded (/lib/systemd/system/php8.2-fpm.service; enabled; vendor preset: enabled)
     Active: active (running) since Fri 2025-12-27 10:55:02 UTC; 16min ago
       Docs: man:php-fpm8.2(8)
    Process: 18110 ExecStartPost=/usr/lib/php/php-fpm-socket-helper install /run/php/php8.2-fpm.sock /etc/php/8.2/fpm/pool.d/www.conf 82 (code=exited, status=0/SUCCESS)
   Main PID: 18106 (php-fpm8.2)
     Status: "Processes active: 1, idle: 5, Requests: 914, slow: 0, Traffic: 0.00req/sec"

Qué significa: Buscas aumentos en los contadores “slow” o inestabilidad después de incrementar la capacidad de parseo.

Decisión: Si las solicitudes lentas aumentan, quizá necesites ajustar los children de FPM, timeouts, o proteger wp-admin con controles de acceso más estrictos en lugar de parseo ilimitado.

Nota sobre seguridad: Cada una de estas tareas es operativamente reversible. No es casualidad. Cuando cambias configuración en producción, quieres que deshacer sea aburrido.

Tres micro-historias corporativas desde el campo

Micro-historia 1: El incidente causado por una suposición equivocada

La empresa tenía un sitio WordPress “dirigido por marketing”, pero no era pequeño. Había múltiples idiomas, cientos de landing pages y una estructura de navegación que seguía acumulándose como percebes. Un martes, la responsable de marketing pidió una limpieza del menú. Un editor pasó una hora reorganizando menús y pulsó guardar.

El sitio no se cayó. Ese fue el problema. Parecía un guardado exitoso, pero el menú perdió un bloque de elementos. El editor los volvió a añadir, guardó otra vez y perdió un bloque distinto. Los tickets de soporte comenzaron con “el encabezado no tiene enlaces”. El equipo de social escaló porque campañas pagadas enviaban tráfico a páginas que de repente no eran accesibles desde la navegación.

Ingeniería asumió que era un problema de caché —porque la mayoría de las rarezas de WordPress en producción sí lo son. Purgaron el CDN, borraron la caché de objetos, reiniciaron PHP-FPM y recargaron Nginx. Sin cambio. La suposición equivocada fue: “Si la interfaz muestra un mensaje de éxito, el servidor aceptó los datos.” No lo había hecho.

La solución fue subir max_input_vars y verificar que la advertencia desapareciera de los logs. La lección más profunda fue cultural: trata las acciones del administrador como escrituras en producción. Regístralas, monitorízalas y no asumas que los “cambios de marketing” son inofensivos. Son cambios en producción con otra interfaz.

Micro-historia 2: La optimización que salió mal

Otra organización estaba obsesionada con “endurecer”. Tenían una lista de control: reducir timeouts, achicar límites, deshabilitar todo lo que pareciera opcional. Alguien notó que PHP tenía por defecto max_input_vars=1000 y decidió que era demasiado generoso. Lo bajaron a 300 globalmente para “reducir la superficie de ataque”.

Nada se rompió de inmediato. El sitio servía páginas bien. El monitoring se mantuvo en verde. Luego el equipo de contenido desplegó un nuevo mega-menú para una campaña estacional, más algunas variantes multilingüe. El editor de menús se convirtió en una máquina tragaperras. A veces guardaba; a veces no; a veces guardaba a medias. La gente culpaba a WordPress. La gente culpaba al plugin de menús. La gente se culpaba entre sí.

La optimización salió mal porque redujo la seguridad para cargas de trabajo legítimas sin mejorar realmente la postura de seguridad. Un atacante que quiera DoS al parser de PHP no se va a detener educadamente en 301 variables; usará otros vectores. Mientras tanto, tus usuarios de negocio ahora tropiezan con un límite que nunca se midió frente al comportamiento real del administrador.

Restauraron el valor a 5000 para el tráfico de wp-admin y lo emparejaron con mejores controles: allowlist de IPs para el admin, rate limiting y reglas WAF que apuntan a patrones realmente maliciosos. La seguridad mejoró. La productividad volvió. La “optimización” se convirtió en historia de precaución cada vez que alguien quería “apretar” un ajuste sin telemetría.

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

Otro equipo ejecutaba WordPress a escala en contenedores. Nada glamoroso: imágenes estándar, GitOps y el tipo de gestión de configuración que aburre a los auditores. Tenían un conjunto conocido de directivas PHP en un archivo de configuración montado, incluyendo max_input_vars. También tenían un job de smoke test que realizaba una operación de guardado en wp-admin en staging usando un fixture de menú grande.

Una semana, un ingeniero subió la imagen base y sin querer cambió el orden de búsqueda del ini de PHP. El archivo montado seguía existiendo, pero no lo leía el proceso FPM. En staging, el smoke test falló: guardar el menú resultó en elementos faltantes, y los logs mostraban la advertencia de max_input_vars.

Porque la práctica era aburrida y automatizada, la falla nunca llegó a producción. Ajustaron el entrypoint del contenedor para asegurar que el fragmento ini aterrizara en el directorio conf.d correcto para esa imagen. La siguiente ejecución del pipeline fue verde, y nadie fuera de ingeniería supo siquiera que hubo un casi accidente.

Ese es el punto. Las mejores victorias de operaciones son las que nadie aplaude porque nada se prendió fuego.

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

1) Elementos de menú desaparecen tras guardar

Síntoma: Guardas un menú grande; los elementos desaparecen o se reordenan de forma extraña.

Causa raíz: Truncamiento por max_input_vars. WordPress guarda datos POST parciales.

Solución: Aumenta max_input_vars para el runtime web (FPM/mod_php) y confirma en logs que la advertencia desaparece.

2) Filas de repeater de ACF desaparecen al actualizar

Síntoma: Subcampos de repeater faltan tras guardar un post.

Causa raíz: El total de input vars excede el límite debido a arrays de campos anidados.

Solución: Aumenta max_input_vars; si alcanzas conteos absurdos, considera refactorizar la estructura de campos o dividir contenido en posts/meta más pequeños.

3) Formularios se envían pero algunos campos llegan vacíos

Síntoma: El email de envío o la carga a CRM falta campos aleatorios.

Causa raíz: Variables de entrada truncadas; el plugin lee claves ausentes como vacías.

Solución: Aumenta max_input_vars y confirma que no hay errores de post_max_size / tamaño del body. También revisa la inflación de cookies si el formulario está cerca del umbral.

4) Aumenté max_input_vars pero nada cambió

Síntoma: Editaste php.ini; la advertencia persiste.

Causa raíz: php.ini equivocado o SAPI equivocado; override a nivel de pool FPM fuerza el valor antiguo; servicio no recargado.

Solución: Usa php-fpmX.Y -i para confirmar “Loaded Configuration File”, busca overrides del pool, recarga el servicio FPM correcto.

5) WP-Admin devuelve 413 Request Entity Too Large

Síntoma: El guardado falla con 413 o una página en blanco.

Causa raíz: Límite de tamaño de body del servidor web (client_max_body_size o LimitRequestBody) en lugar del conteo de input vars.

Solución: Aumenta el límite relevante para las rutas wp-admin solo si es posible; no lo abras globalmente salvo que tengas razón para hacerlo.

6) Guardados aleatorios del admin fallan solo para algunos usuarios

Síntoma: Un editor no puede guardar formularios grandes; otro sí.

Causa raíz: Diferencias en cookies. Algunos usuarios cargan conjuntos de cookies mayores (segmentos analíticos, herramientas de previsualización), lo que les hace superar el límite.

Solución: Reduce la inflación de cookies para wp-admin, asegúrate de que las herramientas de consentimiento no inyecten cookies de marketing en sesiones admin y aumenta max_input_vars si es necesario.

7) Aumentaste límites y la memoria de PHP-FPM subió

Síntoma: Tras el cambio, los workers de FPM usan más memoria o hay OOM kills bajo carga.

Causa raíz: Cargas de parseo mayores por petición incrementan el uso de memoria; las solicitudes de wp-admin son pesadas y serializadas.

Solución: Usa un valor sensato, ajusta FPM (children, límites de memoria) y restringe el acceso al admin. No “arregles” esto con valores ilimitados y esperar que funcione.

Listas de verificación / plan paso a paso

Paso a paso: arreglo seguro en producción para un guardado de menú roto

  1. Reproduce y marca con timestamp la falla. Quieres un punto de correlación en los logs.
  2. Revisa logs en busca de la advertencia explícita. Si está presente, procede; si no, no te estanques.
  3. Identifica el runtime (FPM/mod_php) y las rutas ini activas. Usa introspección de FPM, no suposiciones.
  4. Sube max_input_vars en un único lugar autorizado. Prefiere un fragmento conf.d dedicado con comentarios.
  5. Recarga el servicio correcto. Recarga FPM para cambios de FPM; recarga Apache para mod_php.
  6. Verifica el valor en tiempo de ejecución. Confirma vía php-fpm -i o salida controlada solo para administradores.
  7. Vuelve a probar el flujo exacto del editor. Mismo menú, mismos pasos, mismo usuario si es posible.
  8. Elimina la instrumentación de depuración temporal. Especialmente los mu-plugins que añadiste para contar.
  9. Monitorea efectos secundarios. Solicitudes lentas, memoria de FPM, tiempos de petición aumentados.

Lista de verificación: no olvides límites adyacentes

  • ¿El servidor devuelve 413? Si sí, es tamaño de body, no input vars.
  • ¿El cuerpo POST es grande? Revisa post_max_size.
  • ¿PHP está agotando tiempo parseando? Revisa max_input_time y timeouts de FPM.
  • ¿Un WAF bloquea POSTs de wp-admin? Revisa 403s en el borde.
  • ¿Las cookies son enormes para usuarios afectados? Compara conteo/tamaño de cookies.

Lista de verificación: valores sensatos y salvaguardas

  • Empieza en 3000 o 5000 para sitios grandes; sube solo con evidencia.
  • Mantén post_max_size y el límite de body del servidor alineados con necesidades reales.
  • Protege wp-admin: MFA, allowlists de IP donde sea factible, rate limits y menor exposición.
  • Registra cambios: configuración en control de versiones o al menos en un sistema de gestión de configuración.
  • Haz que el rollback sea fácil: un archivo, una recarga, un comando de verificación.

Preguntas frecuentes

1) ¿Cuál es el valor por defecto de max_input_vars en PHP?

Suele ser 1000, pero “por defecto” puede variar: paquetes de la distro, paneles de hosting y builds endurecidos pueden cambiarlo. Verifica el valor activo en el runtime.

2) ¿Por qué WordPress dice “Menú guardado” cuando no guardó todo?

Porque WordPress solo ve lo que PHP parseó. Si PHP trunca entradas, WordPress recibe un dataset válido (pero incompleto) y lo procesa normalmente.

3) ¿Es esto un bug de WordPress?

No. Es un límite de parseo del lado del servidor en PHP. Se podría argumentar que WordPress podría avisar mejor, pero la causa raíz es configuración y tamaño de la solicitud.

4) ¿Qué tan alto debo poner max_input_vars?

Para muchos sitios, 3000–5000 funciona. Productos variables de WooCommerce y constructores pesados pueden necesitar 10000+. Mide y luego fija el valor más pequeño que evite truncamiento.

5) Si aumento max_input_vars, ¿tengo que reiniciar algo?

Sí. Para PHP-FPM debes recargar/reiniciar el servicio FPM. Recargar Nginx o Apache solo no aplicará cambios de ini de PHP a menos que uses mod_php.

6) Cambié php.ini pero phpinfo aún muestra el valor antiguo. ¿Por qué?

Lo más común: editaste el php.ini equivocado (CLI vs FPM), hay un override a nivel de pool que fuerza otro valor o no recargaste el servicio. Usa php-fpm -i para confirmar los archivos de configuración cargados.

7) ¿Las cookies realmente pueden afectar problemas de max_input_vars?

Sí. Las cookies también son variables de entrada. Usualmente el cuerpo POST es el principal culpable, pero cargas grandes de cookies pueden empujar solicitudes borde al límite.

8) ¿Hay un inconveniente de seguridad al aumentarlo?

Puedes aumentar la carga de parseo y el uso de memoria por petición, lo que puede ser abusado en escenarios DoS. Mitiga con controles de acceso a wp-admin, rate limiting, reglas WAF y límites razonables de tamaño de petición.

9) ¿max_input_vars afecta las subidas de archivos?

No directamente. Las subidas se rigen por límites de tamaño (upload_max_filesize, post_max_size y límites del servidor web). Pero los formularios de subida también pueden tener muchos campos, así que ambos importan.

10) ¿Puedo arreglarlo en WordPress sin tocar la configuración del servidor?

A veces puedes reducir el número de variables de entrada simplificando menús, dividiendo formularios, reduciendo la complejidad de repeaters o evitando plugins que generan campos ocultos masivos. Pero si el sitio necesita legítimamente la complejidad, la solución correcta es configurar el servidor.

Conclusión: pasos siguientes seguros en producción

Si los menús o formularios complejos de WordPress “se guardan” pero en realidad no se guardan, trátalo como pérdida de datos. No es una molestia. El culpable más común es el truncamiento por max_input_vars, y es diagnosticable con logs y un par de comprobaciones en tiempo de ejecución.

Haz esto a continuación, en orden:

  1. Reproduce la falla y revisa los logs de PHP-FPM buscando la advertencia “Input variables exceeded”.
  2. Confirma qué runtime de PHP sirve wp-admin y de dónde carga su configuración.
  3. Sube max_input_vars a un valor medido (a menudo 5000), recarga el servicio correcto y verifica el valor en runtime.
  4. Vuelve a probar el flujo exacto del administrador y vigila límites adyacentes (413s, tamaños/timeouts).
  5. Pon el cambio de configuración en un lugar durable (fragmento conf.d, IaC, montaje de contenedor) para que sobreviva al siguiente despliegue.

La mejor solución es la que no requiere heroísmos a las 4 a.m. Fíjalo, verifícalo y haz que el cambio sea reproducible. Tus editores nunca te lo agradecerán. Así sabrás que funcionó.

← Anterior
DNS: Problemas de MTU pueden romper DNS — Cómo probarlo y solucionarlo
Siguiente →
DNS de WireGuard no funciona a través de la VPN: Configuración correcta de DNS en Linux y Windows

Deja un comentario