No hay nada que demuestre más amor por las fechas límite que un equipo de marketing intentando subir un vídeo principal de 120 MB cinco minutos antes del lanzamiento—y encontrarse con “exceeds the maximum upload size for this site” o el clásico “exceeds upload_max_filesize”.
Este error nunca es un único control. Es una cadena. PHP tiene límites. El servidor web tiene límites. Proxies y CDN tienen límites. WordPress tiene sus propias reglas. El panel de hosting tiene valores por defecto “útiles”. Arreglarlo correctamente significa encontrar el eslabón más pequeño, subirlo intencionadamente y verificar qué cambió realmente.
Guía rápida de diagnóstico
Si no haces nada más, haz esto. Convierte “cambié php.ini y no pasó nada” en un ticket breve y aburrido. Aburrido es bueno.
1) Identifica la superficie real del error: mensaje de WordPress, estado HTTP o registro del servidor
- Si el navegador muestra HTTP 413 o una página simple de Nginx/Cloudflare: estás bloqueado antes de que PHP intervenga. Arregla primero el proxy/servidor web.
- Si WordPress muestra “exceeds upload_max_filesize” o “exceeds the maximum upload size”: probablemente estás tropezando con límites de PHP (o WordPress está leyendo los límites de PHP y los reporta).
- Si la subida gira y luego falla con “link expired” / “failed to write file to disk” / “missing a temporary folder”: no es un límite de tamaño; son problemas de sistema de archivos, tmp o permisos.
2) Encuentra el límite más pequeño en la cadena
Las subidas fallan en el mínimo de:
- Comportamientos del cliente/navegador (raro, pero en móviles puede expirar)
- Límite de cuerpo de la petición en CDN/WAF/proxy
- Límite de cuerpo de petición del servidor web (Nginx/Apache)
- Límites de la SAPI de PHP:
upload_max_filesize,post_max_size,memory_limit, timeouts - Restricciones de disco: espacio libre, partición tmp, agotamiento de inodos
- Restricciones de WordPress y plugins (menos comunes, pero reales)
3) Verifica qué está usando PHP realmente (no adivines)
PHP puede cargar distintos archivos ini según la SAPI (FPM vs CLI), el pool y el empaquetado de la distro. Confirma el ini cargado y los valores efectivos.
4) Cambia una capa a la vez y reinicia el servicio correcto
Reiniciar el demonio equivocado es un rito de iniciación. También una pérdida de tiempo. Cambia la configuración correcta, valida la sintaxis, recarga/reinicia y luego prueba.
5) Vuelve a probar con un tamaño de subida que debería fallar y otro que debería pasar
Probar con un archivo de 2 MB después de “aumentarlo a 512 MB” no te dice nada. Elige un archivo del 50–80% del nuevo límite y prueba otra vez.
Una cita para tu runbook: La esperanza no es una estrategia.
(General H. Norman Schwarzkopf)
Qué significa realmente el error (y qué no)
“exceeds upload_max_filesize” es PHP hablando—específicamente del subsistema de subida de archivos. Se lanza cuando PHP se niega a aceptar un archivo porque es más grande que upload_max_filesize. WordPress normalmente lo muestra como un mensaje amigable en el cargador de medios.
Pero la realidad en producción es desordenada. Puedes ver este mensaje incluso si:
- Tu proxy bloquea el cuerpo de la petición y WordPress intuye el límite a partir de la configuración de PHP (subes PHP, WordPress muestra un número mayor, pero las subidas siguen muriendo en el borde).
- Editaste el
php.iniequivocado (común en hosts con múltiples PHP, contenedores, o cuando CLI != FPM). post_max_sizesigue siendo menor queupload_max_filesize(tu archivo está dentro de upload_max_filesize, pero el cuerpo POST completo no lo está).- Estás alcanzando timeouts (subidas grandes por enlaces lentos), no límites de tamaño.
Además: el error no dice nada sobre el disco. Puedes aumentar límites a 2 GB y seguir fallando porque /tmp es pequeño o el volumen está lleno. Las subidas no son magia; aterrizan en algún sitio.
La cadena de límites de subida: dónde se bloquean las subidas
Piense en una subida de WordPress como un paquete que pasa por controles. Cualquier control puede rechazarlo. Tu trabajo es encontrar qué guardia lo detiene.
Checkpoint A: CDN/WAF/reverse proxy
Si tienes Cloudflare, un WAF gestionado, un ALB/ELB, una pasarela API o un controlador de ingreso Nginx, probablemente tengas un tope de tamaño de petición y, a veces, un comportamiento de buffering que cambia cómo funcionan las subidas grandes.
Checkpoint B: Servidor web
Nginx viene por defecto con un límite de cuerpo de petición bastante pequeño en muchas configuraciones (client_max_body_size). Apache también puede aplicar tamaño de cuerpo con directivas como LimitRequestBody (aunque no siempre esté activado por defecto).
Checkpoint C: SAPI de PHP (FPM/mod_php)
El trío clásico:
upload_max_filesize: límite por archivo.post_max_size: límite total del cuerpo POST (debe ser mayor que upload_max_filesize; añade margen).memory_limit: afecta al procesamiento y a algunos plugins; no siempre necesita ser mayor que el tamaño del archivo, pero en la práctica conviene margen.
También vigila:
max_execution_time,max_input_time: timeouts para subidas lentas y procesamiento PHP.max_file_uploads: número de archivos por petición (rara vez un problema en WordPress, pero plugins de subida masiva pueden alcanzarlo).upload_tmp_dir: dónde PHP escribe archivos temporales; si apunta a un sistema de archivos pequeño, pierdes.
Checkpoint D: Sistema de archivos y SO
Las subidas se escriben en espacio temporal y luego en wp-content/uploads (o donde esté configurado). Modos de fallo:
- Disco lleno o agotamiento de inodos
- Permisos/propietario incorrectos
- Las banderas de montaje
noexecnormalmente no afectan a medios, pero las políticas SELinux/AppArmor pueden - El almacenamiento de overlay del contenedor se llena mientras el volumen adjunto tiene espacio
Checkpoint E: WordPress y plugins
WordPress informa “Maximum upload file size” basándose en lo que PHP le dice. Los plugins pueden añadir su propia validación, y algunos plugins de seguridad bloquean ciertos tipos MIME o extensiones, que los usuarios a veces interpretan erróneamente como errores de tamaño.
Datos interesantes y breve historia de los límites de subida
- El límite por defecto de PHP solía ser diminuto por diseño. Valores por defecto como 2 MB eran comunes porque el hosting compartido de los 2000 era una lucha por recursos.
post_max_sizeimporta incluso para subidas de un solo archivo. El archivo forma parte de un formulario multipart; el cuerpo completo incluye límites y campos, así que necesitas margen.- Nginx rechaza cuerpos sobredimensionados pronto. Cuando se excede
client_max_body_size, Nginx puede devolver 413 sin tocar PHP-FPM. Eso protege los backends, pero confunde a las personas. - “413 Request Entity Too Large” es más antiguo que la mayoría de sitios WordPress. Es un estado HTTP de la época en que “entity” era lenguaje común en especificaciones para la carga de solicitudes.
- WordPress no “fija” los límites de PHP. Los lee. Cualquier ajuste en el panel que diga cambiar PHP está o escribiendo archivos de configuración o mintiendo educadamente.
- PHP-FPM y PHP CLI son SAPIs diferentes. El CLI puede mostrarte valores razonables mientras FPM usa archivos ini distintos. Muchos incidentes empiezan con alguien ejecutando
php -iy confiando en eso. - Las subidas normalmente pisan primero el espacio temporal. PHP escribe en un archivo temporal antes de moverlo. Si
/tmpestá en una partición pequeña, las subidas grandes fallan aunque el volumen final tenga espacio. - Los CDN suelen limitar el tamaño de petición en planes inferiores. Puedes subir Nginx y PHP todo lo que quieras y seguir fallando en el borde. El borde no negocia.
- Las subidas de medios grandes se normalizaron recientemente. Los móviles modernos graban en 4K por defecto; clips “rápidos” de 200 MB son hoy estándar y acabarán con límites de 2 MB con entusiasmo.
Tareas prácticas: comandos, salidas, decisiones (12+)
Estos son los movimientos que espero que un SRE ejecute en un host real. Cada tarea incluye: el comando, qué significa la salida y la decisión que tomas.
Task 1: Confirmar los límites efectivos de PHP (comprobación de sanity en CLI)
cr0x@server:~$ php -r 'echo "upload_max_filesize=",ini_get("upload_max_filesize"),"\npost_max_size=",ini_get("post_max_size"),"\nmemory_limit=",ini_get("memory_limit"),"\n";'
upload_max_filesize=2M
post_max_size=8M
memory_limit=128M
Qué significa: Esta es la vista de PHP CLI. Puede no coincidir con PHP-FPM o mod_php.
Decisión: Si CLI ya está alto pero WordPress sigue fallando, deja de editar archivos ini al azar y verifica la SAPI web a continuación.
Task 2: Identificar qué SAPI de PHP estás ejecutando (FPM vs módulo de Apache)
cr0x@server:~$ ps -ef | egrep 'php-fpm|apache2|httpd' | head
root 1012 1 0 09:00 ? 00:00:02 php-fpm: master process (/etc/php/8.2/fpm/php-fpm.conf)
www-data 1044 1012 0 09:00 ? 00:00:00 php-fpm: pool www
root 1200 1 0 09:00 ? 00:00:01 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
Qué significa: Estás en Nginx + PHP-FPM. Las ediciones deben dirigirse a la configuración de FPM/pool, no a Apache.
Decisión: Procede a las ubicaciones de configuración de FPM y recarga PHP-FPM y Nginx.
Task 3: Encontrar el php.ini cargado para PHP-FPM (no CLI)
cr0x@server:~$ php-fpm8.2 -i | egrep 'Loaded Configuration File|Scan this dir for additional .ini files'
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: Ese es el ini y el directorio escaneado para la SAPI FPM.
Decisión: Edita /etc/php/8.2/fpm/php.ini o crea un override dedicado en conf.d, luego recarga PHP-FPM.
Task 4: Comprobar los valores efectivos en el ini de FPM
cr0x@server:~$ sudo egrep -n '^(upload_max_filesize|post_max_size|memory_limit|max_execution_time|max_input_time)' /etc/php/8.2/fpm/php.ini
861:upload_max_filesize = 2M
701:post_max_size = 8M
436:memory_limit = 128M
409:max_execution_time = 30
415:max_input_time = 60
Qué significa: Estos son los valores configurados actualmente para FPM.
Decisión: Súbelos a valores acordes con las subidas esperadas y luego recarga PHP-FPM. Asegúrate también de que post_max_size sea mayor que upload_max_filesize.
Task 5: Comprobar el límite de cuerpo de petición de Nginx en la configuración
cr0x@server:~$ sudo nginx -T 2>/dev/null | egrep -n 'client_max_body_size'
45: client_max_body_size 1m;
212: client_max_body_size 16m;
Qué significa: Tienes varios ámbitos. El bloque más específico que coincida gana.
Decisión: Establece client_max_body_size donde tu vhost de WordPress realmente coincida (usualmente en el bloque server). Elimina valores contradictorios si puedes.
Task 6: Validar la configuración de Nginx antes de recargar
cr0x@server:~$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Qué significa: Seguro para recargar. Si la sintaxis falla, no recargues; arregla el archivo primero.
Decisión: Recarga Nginx solo tras un -t limpio.
Task 7: Recargar servicios correctamente (y verificar que realmente se recargaron)
cr0x@server:~$ sudo systemctl reload nginx
cr0x@server:~$ sudo systemctl reload php8.2-fpm
cr0x@server:~$ systemctl is-active nginx php8.2-fpm
active
active
Qué significa: La recarga tuvo éxito y los servicios siguen activos.
Decisión: Si la recarga falla o un servicio no está activo, para—soluciona el servicio antes de probar subidas.
Task 8: Inspeccionar overrides de pool de PHP-FPM (pueden limitar silenciosamente)
cr0x@server:~$ sudo egrep -n 'php_admin_value\[(upload_max_filesize|post_max_size|memory_limit)\]|request_terminate_timeout' /etc/php/8.2/fpm/pool.d/www.conf
;php_admin_value[upload_max_filesize] = 10M
;php_admin_value[post_max_size] = 12M
;request_terminate_timeout = 0
Qué significa: Aquí están comentados, pero en algunos sistemas estos están activos y anulan el php.ini.
Decisión: Si existen overrides de pool, establece los valores allí de forma intencionada, documenta y deja de pretender que php.ini es la autoridad.
Task 9: Comprobar directivas de tamaño de cuerpo en Apache (si ejecutas Apache)
cr0x@server:~$ sudo apachectl -M | head -n 5
Loaded Modules:
core_module (static)
so_module (static)
watchdog_module (static)
http_module (static)
Qué significa: Apache está presente; si es tu frontend, necesitas comprobar los límites de Apache e integración con PHP (mod_php o proxy_fcgi).
Decisión: Si estás en Apache, busca LimitRequestBody y revisa la configuración del vhost.
Task 10: Buscar en la configuración de Apache límites de tamaño de petición
cr0x@server:~$ sudo grep -R --line-number -E 'LimitRequestBody' /etc/apache2/sites-enabled /etc/apache2/apache2.conf 2>/dev/null
/etc/apache2/sites-enabled/000-default.conf:27:LimitRequestBody 10485760
Qué significa: Apache está limitado a 10 MB en ese vhost. Los cambios en PHP no importarán.
Decisión: Eleva LimitRequestBody (o elimínalo si controlas límites en otro sitio), luego recarga Apache.
Task 11: Confirmar espacio en disco y disponibilidad de inodos (las subidas necesitan ambos)
cr0x@server:~$ df -h /var/www/html /tmp
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 80G 62G 15G 81% /
tmpfs 1.0G 120M 904M 12% /tmp
cr0x@server:~$ df -i /var/www/html /tmp
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/vda1 5242880 910000 4332880 18% /
tmpfs 262144 980 261164 1% /tmp
Qué significa: Tienes 15 GB libres y los inodos están bien. /tmp es 1 GB, lo que puede resultar ajustado para subidas grandes.
Decisión: Si quieres permitir subidas de 2 GB, debes ampliar el almacenamiento temporal o configurar upload_tmp_dir a un sistema de archivos mayor.
Task 12: Comprobar el tamaño máximo de subida que informa WordPress (lo que ve el administrador)
cr0x@server:~$ sudo -u www-data php /var/www/html/wp-admin/includes/file.php 2>/dev/null || true
Qué significa: No es la mejor forma de consultar WordPress, pero recuerda: WordPress es código PHP. El valor en la interfaz de administración se deriva de ajustes de PHP, no al revés.
Decisión: Usa un check phpinfo() en contexto web si es necesario (ver tarea siguiente), y luego elimínalo.
Task 13: Crear una página phpinfo temporal para confirmar valores FPM (luego bórrala)
cr0x@server:~$ sudo tee /var/www/html/phpinfo.php >/dev/null <<'EOF'
/etc/php/8.2/fpm/php.ini
Qué significa: Ahora inspeccionas PHP servido por la pila web, que es lo que importa.
Decisión: Confirma los valores; luego borra phpinfo.php. Dejarlo es una invitación a problemas.
Task 14: Inspeccionar logs por 413 o errores de subida de PHP
cr0x@server:~$ sudo tail -n 50 /var/log/nginx/error.log
2025/12/27 09:22:18 [error] 1432#1432: *991 client intended to send too large body: 24681231 bytes, client: 203.0.113.9, server: example.com, request: "POST /wp-admin/async-upload.php HTTP/1.1", host: "example.com", referrer: "https://example.com/wp-admin/media-new.php"
Qué significa: Esto no es PHP. Nginx está rechazando el cuerpo de la petición (aquí ~24.6 MB).
Decisión: Eleva client_max_body_size en el ámbito correcto. No toques PHP hasta que Nginx deje de hacer de portero.
Task 15: Validar el log de PHP para fallos específicos de subida
cr0x@server:~$ sudo tail -n 50 /var/log/php8.2-fpm.log
[27-Dec-2025 09:25:10] WARNING: [pool www] child 2123 said into stderr: "PHP message: PHP Warning: POST Content-Length of 52459012 bytes exceeds the limit of 8388608 bytes in Unknown on line 0"
Qué significa: post_max_size es 8 MB (8388608 bytes). El usuario intentó ~52 MB. PHP lo rechazó antes de que WordPress pudiera hacer nada significativo.
Decisión: Aumenta post_max_size por encima del máximo de subida deseado, con margen.
Task 16: Confirmar que un proxy/CDN no esté imponiendo un tope menor (ejemplo: Cloudflare vía cabeceras)
cr0x@server:~$ curl -I -sS https://example.com/wp-admin/media-new.php | egrep -i 'server:|cf-ray|via:|x-cache'
server: cloudflare
cf-ray: 88f0c1d2ab123456-LHR
Qué significa: Cloudflare está en el camino. Los límites de tamaño de subida pueden depender del plan y manifestarse como errores 413/520.
Decisión: Si ves participación del edge, reproduce evitando ese camino (prueba directa al origin) o revisa la configuración de límites del edge. No asumas que el origin es el problema.
Chiste 1: Los límites de subida son como las políticas de gastos corporativas—todo el mundo los descubre solo cuando intenta hacer algo normal.
Solución por pila: Apache, Nginx, PHP-FPM, proxies, paneles, contenedores
Elige límites sensatos (y deja de usar “simplemente ponlo a 2G” como plan)
Empieza con un requisito real: “Necesitamos subir vídeos de hasta 200 MB” o “Necesitamos 64 MB para PDFs”. Luego ajusta:
upload_max_filesize= requisito (p. ej., 256M)post_max_size= upload_max_filesize + overhead (p. ej., 300M)memory_limit= depende de plugins y procesamiento de imágenes; para WP con mucho media, 256M–512M es común- Límite de cuerpo del servidor web/proxy = al menos post_max_size
Si permites subidas enormes, también planifica ancho de banda, timeouts y crecimiento del almacenamiento. “Las subidas funcionan” no es lo mismo que “las subidas no arrasan el servidor el mes que viene”.
Nginx + PHP-FPM (configuración moderna más común)
1) Elevar client_max_body_size en Nginx
Establécelo en el bloque server correcto (o en http si quieres global). Ejemplo de vhost:
cr0x@server:~$ sudo tee /etc/nginx/sites-available/example.com.conf >/dev/null <<'EOF'
server {
listen 80;
server_name example.com;
root /var/www/html;
client_max_body_size 300m;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
}
EOF
Decisión: Ajusta Nginx al menos a post_max_size. Si pones Nginx menor que PHP, los usuarios obtendrán 413; si pones PHP menor que Nginx, los usuarios verán errores de PHP/WordPress. En cualquier caso, recibirás un ticket.
2) Aumentar límites de PHP-FPM en el ini correcto
Edita el ini de FPM o coloca un archivo override en conf.d (más limpio para gestión de configuración).
cr0x@server:~$ sudo tee /etc/php/8.2/fpm/conf.d/99-wordpress-uploads.ini >/dev/null <<'EOF'
upload_max_filesize = 256M
post_max_size = 300M
memory_limit = 512M
max_execution_time = 120
max_input_time = 120
EOF
Decisión: Usa un override con nombre claro. Facilita auditorías e incident response más que hurgar en un php.ini del proveedor.
3) Recargar y verificar vía phpinfo en contexto web
Recarga FPM y Nginx. Confirma en el phpinfo servido que los nuevos valores están activos. Luego elimina phpinfo.
Configuraciones Apache
Apache puede ejecutar PHP vía mod_php (antiguo) o vía PHP-FPM (proxy_fcgi). Los límites difieren según la integración.
Techos de cuerpo de petición en Apache
Si tienes LimitRequestBody en tu vhost o contexto de directorio, es un techo duro. Súbelo (en bytes) o elimínalo si controlas límites en otro sitio.
cr0x@server:~$ sudo sed -i 's/LimitRequestBody 10485760/LimitRequestBody 314572800/' /etc/apache2/sites-enabled/000-default.conf
cr0x@server:~$ sudo apachectl configtest
Syntax OK
cr0x@server:~$ sudo systemctl reload apache2
Decisión: Si usas Apache como reverse proxy frente a FPM, alinea el tamaño de cuerpo de Apache con el post_max_size de PHP.
Límites de PHP (mod_php vs FPM)
Si ejecutas mod_php, la ruta ini suele ser /etc/php/X.Y/apache2/php.ini. Si ejecutas FPM, es /etc/php/X.Y/fpm/php.ini. No “arregles” el ini de Apache si Apache no sirve PHP directamente.
Proxies inversos y balanceadores
Responsables comunes:
- Nginx delante de Nginx (sí, en serio). Cada capa puede tener su propio
client_max_body_size. - Controladores de ingreso en Kubernetes con sus propios ajustes de cuerpo de petición.
- Reglas WAF que bloquean cuerpos grandes o ciertos patrones multipart.
El método es el mismo: encuentra qué capa emite 413 (o reinicia la conexión), luego sube ese límite. Si puedes evitar temporalmente el proxy (origin directo), hazlo para acotar el problema.
cPanel / Plesk / paneles de hosting gestionado
Los paneles suelen ofrecer toggles para “aumentar tamaño de subida”. Bajo el capó editan ini o configs por sitio. La trampa es la configuración en conflicto:
- El panel escribe en un ini mientras tu sitio usa otra versión de PHP o handler.
- El panel eleva PHP, pero Nginx/Apache sigue limitando el cuerpo.
- Los cambios del panel son sobrescritos por actualizaciones o por tu gestión de configuración.
Usa el panel si ese es tu modelo de gobernanza, pero verifica con phpinfo y registros. Los paneles son UI, no la verdad absoluta.
Docker y WordPress en contenedores
Los contenedores añaden dos problemas clásicos:
- Puedes estar editando un archivo de configuración en el host que el contenedor no usa.
- El proxy frontal (Traefik/Nginx/Ingress) a menudo tiene el tope real, no el contenedor PHP.
Si ejecutas la imagen oficial de WordPress con Apache, normalmente ajustas PHP mediante snippets ini montados en el contenedor.
cr0x@server:~$ docker exec -it wordpress php -i | egrep 'Loaded Configuration File|upload_max_filesize|post_max_size' | head
Loaded Configuration File => /usr/local/etc/php/php.ini
upload_max_filesize => 2M => 2M
post_max_size => 8M => 8M
Decisión: Si el contenedor aún muestra 2M/8M, necesitas montar un override ini en /usr/local/etc/php/conf.d (o reconstruir la imagen), luego reiniciar el contenedor.
Capa de WordPress: qué importa y qué es cargo cult
“Maximum upload file size” de WordPress es una visualización de síntoma
En Medios → Añadir nuevo, WordPress muestra un máximo. Ese número suele derivarse de upload_max_filesize y post_max_size de PHP, a veces con lógica extra. No es una garantía de que toda la cadena soporte ese tamaño.
“Trucos” en wp-config.php
Verás consejos de añadir constantes o llamadas ini_set en wp-config.php:
ini_set('upload_max_filesize','256M')define('WP_MEMORY_LIMIT','256M')
La verdad: ini_set() no puede cambiar ajustes con PHP_INI_SYSTEM en muchas configuraciones, y un php_admin_value en FPM puede bloquearlo por completo. Si funciona, es frágil. Si no funciona, la gente pierde días creyendo que WordPress los ignoró por despecho.
Prefiere el enfoque aburrido y ejecutable: ajusta límites de PHP en ini/pool, límites del servidor web en la configuración del servidor, y verifica en logs.
El límite de memoria no es un límite de subida (pero aún puede matar las subidas)
Subir un archivo no requiere que PHP mantenga todo el archivo en memoria; se streamnea a un archivo temporal. Pero los plugins pueden procesar archivos (redimensionar imágenes, extraer metadatos de vídeo, previsualizar PDFs) y consumir memoria. Si subes límites y de repente ves pantallas blancas o errores fatales tras la subida, suele ser memoria o tiempo de ejecución durante el procesamiento, no la subida en sí.
Bloqueos por MIME y extensiones que se disfrazan de “errores de subida”
Algunos hosts bloquean ciertas extensiones. WordPress también tiene restricciones MIME para subidas. Cuando un usuario oye “subida fallida”, asume tamaño. Revisa el mensaje real y los logs. Un SVG, EXE o un contenedor de vídeo inusual bloqueado no es un problema de tamaño.
Chiste 2: “Simplemente aumenta el límite” es el equivalente operativo de “¿has intentado apagarlo y encenderlo?”—a veces correcto, siempre sospechoso.
Errores comunes (síntoma → causa raíz → solución)
1) Síntoma: WordPress dice máximo 256MB, pero las subidas fallan con HTTP 413
Causa raíz: El límite de cuerpo de petición de Nginx/edge proxy es menor que PHP.
Solución: Eleva client_max_body_size (y cualquier tope del proxy upstream). Confirma en el log de Nginx que ya no ves “client intended to send too large body”.
2) Síntoma: Edité php.ini, reinicié PHP, nada cambió
Causa raíz: Editaste el ini equivocado (CLI vs FPM vs Apache), o un override de pool lo está sobreescribiendo.
Solución: Revisa el archivo de configuración cargado por la SAPI web con phpinfo; busca php_admin_value en los pools.
3) Síntoma: La subida falla en ~8MB o ~16MB exactamente, independientemente de los ajustes
Causa raíz: Tope en dispositivo upstream (WAF, ALB, controlador de ingreso), o LimitRequestBody en Apache.
Solución: Identifica la capa que devuelve 413 mediante logs y cabeceras; sube ese límite. No subas PHP a ciegas primero.
4) Síntoma: La subida empieza y luego falla con “The link you followed has expired.”
Causa raíz: A menudo timeouts o expiración de nonce durante subidas lentas; a veces max_execution_time o timeouts del proxy.
Solución: Aumenta timeouts de PHP y de lectura del proxy; asegúrate de que el usuario no esté subiendo por un enlace dolorosamente lento respecto a los timeouts del servidor.
5) Síntoma: La subida falla con “Missing a temporary folder” o “Failed to write file to disk”
Causa raíz: upload_tmp_dir mal configurado, permisos erróneos, disco lleno o /tmp demasiado pequeño.
Solución: Revisa df -h, df -i, permisos en /tmp y wp-content/uploads, y apunta upload_tmp_dir a una ruta escribible con espacio.
6) Síntoma: Solo fallan imágenes grandes; las pequeñas sí funcionan
Causa raíz: El procesamiento de imagen tras la subida alcanza memory_limit o max_execution_time; o un plugin realiza procesamiento pesado.
Solución: Aumenta memory_limit, perfila el comportamiento del plugin, considera externalizar el redimensionado o limitar los tamaños generados automáticamente.
7) Síntoma: Funciona cuando se evita la CDN, falla a través de la CDN
Causa raíz: Tope de cuerpo en el edge o regla WAF que bloquea multipart/form-data.
Solución: Ajusta la configuración del CDN/WAF, o enruta subidas de admin/media directamente al origin si tu arquitectura lo permite.
Listas de verificación / plan paso a paso
Paso a paso: aumentar límites de forma segura en Nginx + PHP-FPM
- Elige un tamaño objetivo de subida. Ejemplo: 256M. Decide
post_max_size=300M. - Revisa bloqueadores actuales: log de Nginx para 413; log de PHP-FPM para “POST Content-Length exceeds”.
- Establece el límite en Nginx en el vhost correcto:
client_max_body_size 300m; - Establece el override de PHP-FPM:
upload_max_filesize,post_max_size, timeouts y opcionalmentememory_limit. - Valida y recarga:
nginx -t, recarga Nginx y PHP-FPM. - Verifica vía phpinfo en contexto web (temporalmente) y bórralo.
- Prueba subidas al 50–80% del límite y justo por encima del límite para confirmar el comportamiento de fallo.
- Vigila disco: Asegura que
/tmpy tu volumen de WordPress soporten subidas concurrentes. - Documenta los nuevos límites en un runbook, incluyendo dónde se configuran.
Checklist: qué alinear entre capas (corrección mínima viable)
client_max_body_size(o equivalente en Apache) ≥post_max_sizepost_max_size≥upload_max_filesize+ overhead- Capacidad de almacenamiento temporal ≥ subida máxima (multiplicada por concurrencia esperada)
- Timeouts de PHP y de proxy consistentes con la duración de subidas
- Configuración del origin, proxy y CDN alineadas (sin topes ocultos más pequeños)
Checklist: salvaguardas operativas (para que “aumentar límites” no acabe en “ups”)
- Decide si quieres permitir subidas grandes solo en administración (algunas pilas permiten aplicar límites por ubicación).
- Añade monitorización: uso de disco, uso de inodos y tasa de errores 413 y advertencias de subida de PHP.
- Mantén un plan de reversión: revertir snippet ini, revertir directiva vhost, recargar servicios.
- Si permites subidas muy grandes, considera externalizar medios a almacenamiento de objetos y usar subidas multipart.
Tres mini-historias del mundo corporativo
Mini-historia 1: El incidente causado por una suposición equivocada
Una empresa retail ejecutaba WordPress como “CMS ligero” detrás de una capa de reverse proxy. Un día, producto lanzó una nueva landing con vídeos cortos. Las subidas empezaron a fallar de forma intermitente, mayormente para personal remoto. El ingeniero on-call vio el error de WordPress sobre upload_max_filesize, editó /etc/php/8.1/fpm/php.ini, aumentó los límites, recargó PHP-FPM y declaró victoria.
La siguiente subida siguió fallando. Mismo mensaje. Aumentaron otra vez los límites, porque si 256M no funcionó, seguro 512M sí. No funcionó. Ahora el equipo tenía dos problemas: las subidas seguían fallando, y PHP estaba configurado para aceptar cargas mayores sin discusión sobre disco, timeouts o resistencia al abuso.
La causa raíz fue dolorosamente mundana: la capa de reverse proxy tenía client_max_body_size fijado a 20M. WordPress reportaba el nuevo límite mayor de PHP, pero el proxy bloqueaba a 20M. Usuarios cercanos a la sede ocasionalmente tenían éxito porque sus archivos eran más pequeños; los remotos subían activos más grandes con más frecuencia.
La solución tomó diez minutos: subir el límite del proxy para que coincida con post_max_size, recargar y añadir una alerta de logs para respuestas 413. La lección real tardó más: deja de asumir que el mensaje de error apunta a la capa equivocada. En sistemas multinivel, el primer componente que rechaza la petición escribe la verdad, y WordPress raramente es ese componente.
Mini-historia 2: La optimización que salió mal
Un sitio con mucho media decidió “optimizar rendimiento” apretando límites en todas partes. Bajaron client_max_body_size en Nginx a 10M porque “nadie debería subir más que eso” y redujo el ruido de bots. También redujeron timeouts de PHP porque las peticiones largas parecían sospechosas.
Luego el negocio empezó a hacer webinars. Marketing necesitaba miniaturas de vídeo de 80M (no preguntes) y subidas de audio de 150M. El personal se arreglaba usando FTP y moviendo archivos manualmente a wp-content/uploads, lo que evitaba la generación de metadatos de WordPress y rompía la biblioteca de medios. Genial para uptime, terrible para coherencia.
El verdadero problema operativo fue el workaround: aumentó pasos manuales y creó estado inconsistente. Algunos archivos estaban en disco pero no en la base de datos. Algunos tenían URLs que nunca se regeneraron tras un cambio de dominio. Cuando finalmente subieron límites, heredaron una pila de “medios fantasma” y un problema de confianza: los usuarios ya no creían que el sistema de subida funcionara, incluso cuando sí lo hacía.
La solución fue no “abrir la compuerta”. Definieron una política clara (256M), alinearon límites en edge, proxy y PHP, y más tarde añadieron offload de medios. Optimizar está bien. Optimizar sin entender flujos de trabajo es cómo acabas con un sistema rápido que no hace el trabajo.
Mini-historia 3: La práctica aburrida y correcta que salvó el día
Una intranet corporativa grande ejecutaba múltiples instancias de WordPress en la misma flota. Nada emocionante. El equipo de plataforma mantenía un conjunto pequeño de defaults endurecidos, incluyendo límites de subida. Pero también aplicaban una regla: cualquier cambio de límites debía hacerse mediante un único snippet de configuración desplegado por automatización y verificado por una comprobación de salud que lea los valores efectivos.
Cuando un sitio nuevo pidió subir vídeos de formación más grandes, el equipo no tocó php.ini directamente. Añadieron un único archivo ini en conf.d, subieron las configuraciones del vhost en Nginx y actualizaron un check canario que subía un archivo ligeramente por debajo del límite a un staging. Luego lo desplegaron de forma gradual.
Dos semanas después, una actualización de la imagen base reemplazó el php.ini del proveedor. Los sitios que habían editado ese archivo a mano habrían vuelto a 2M y provocado un incendio en soporte. Esta flota no. El snippet override sobrevivió, la comprobación canaria siguió pasando y nadie lo notó.
Esto es lo que compra lo “aburrido”: inmunidad frente a cambios que arruinan un viernes por la noche. A la gente le gustan las soluciones ingeniosas. La producción ama las reproducibles.
FAQ
1) ¿Cuál es la diferencia entre upload_max_filesize y post_max_size?
upload_max_filesize limita un solo archivo subido. post_max_size limita todo el cuerpo HTTP POST. Para subidas de archivos, el cuerpo POST siempre es mayor que el archivo por la sobrecarga multipart. Ajusta post_max_size más alto.
2) Aumenté upload_max_filesize pero WordPress sigue mostrando el límite antiguo. ¿Por qué?
O editaste el ini de PHP equivocado (CLI vs FPM vs Apache), el cambio no se recargó o otra configuración (override de pool php_admin_value) lo sobreescribe. Confirma usando una página phpinfo en contexto web.
3) ¿Por qué obtengo HTTP 413 en vez de un error de WordPress?
Porque algo delante de WordPress rechazó el cuerpo de la petición antes de que PHP lo viera—a menudo client_max_body_size de Nginx, LimitRequestBody de Apache, un balanceador o un CDN.
4) ¿Necesito aumentar memory_limit para que coincida con mi tamaño de subida?
No estrictamente para la transferencia, pero sí a menudo para lo que sucede después: redimensionado de imágenes, extracción de metadatos, previsualizaciones PDF, procesamiento por plugins. Si las subidas tienen éxito pero el procesamiento falla, la memoria es sospechosa.
5) ¿Qué tan altos debo poner los límites de subida para WordPress?
Pónlos al valor más pequeño que soporte las necesidades reales de los usuarios con algo de margen. Para muchos sitios, 64M–256M es práctico. Si necesitas más, considera offload de medios a almacenamiento de objetos y revisa timeouts y capacidad de disco.
6) ¿Puedo establecer límites en .htaccess?
A veces, en Apache con mod_php, directivas como php_value upload_max_filesize en .htaccess pueden funcionar. En PHP-FPM normalmente no. Trata la afinación de .htaccess como legado y verifica resultados.
7) ¿Por qué las subidas fallan solo para algunos usuarios o redes?
Enlaces de subida lentos pueden chocar con timeouts. Proxies corporativos pueden interferir. Además, los usuarios pueden subir archivos distintos. Revisa timeouts, comprueba si las protecciones del edge varían por región y prueba desde la red del origin.
8) ¿Aumentar límites de subida es un riesgo de seguridad?
Puede serlo. Cuerpos más grandes significan más exposición de recursos: ancho de banda, disco temporal, CPU para procesado y peticiones más largas. Establece límites de forma intencionada, aplica ámbito si es posible (rutas de admin) y monitoriza.
9) ¿Cómo sé qué capa está bloqueando la subida?
Busca 413 en el navegador y en logs de Nginx/Apache. Si Nginx registra “client intended to send too large body”, es Nginx. Si PHP registra “POST Content-Length exceeds”, es PHP. Si ninguno, sospecha CDN/WAF o problemas de sistema de archivos.
10) ¿Por qué funcionó ayer y falla hoy sin cambios?
Razones comunes: una actualización de paquete reemplazó configs, un panel reinició ajustes, se llenó el disco o cambió la política del proxy/WAF. Por eso los snippets de configuración + verificaciones son valiosos.
Conclusión: próximos pasos que no te morderán después
Arreglar “exceeds upload_max_filesize” no consiste en encontrar la línea mágica de php.ini. Se trata de alinear límites en toda la ruta de la petición y demostrar la configuración efectiva en contexto web.
Haz lo siguiente:
- Ejecuta la guía rápida de diagnóstico e identifica si el bloqueador está en el edge, servidor web o PHP.
- Define un tamaño objetivo claro y alinea
client_max_body_size/LimitRequestBody,post_max_sizeyupload_max_filesize. - Recarga los servicios correctos y verifica usando phpinfo servido (brevemente) y los logs.
- Revisa disco y almacenamiento temporal. Si permites subidas grandes, planifica concurrencia y crecimiento.
- Apunta dónde viven los ajustes. El tú futuro es un extraño; déjale un mapa.