Fixing the upload_max_filesize Error in WordPress
The limit is PHP's, not WordPress's, and raising it in wp-config.php cannot work because the directive is read before any PHP script runs. Where it can be raised depends on the server, and two other limits sit behind it.
The limit is PHP's, and the one place everyone tries first cannot change it. "The uploaded file exceeds the upload_max_filesize directive in php.ini" means PHP refused the file before WordPress saw it. The media library usually stops an oversized file earlier, in the browser, with "exceeds the maximum upload size for this site"; the php.ini wording appears on the paths that skip that check — plugin and theme zips, importers, the browser uploader — and both point at the same setting. upload_max_filesize is read at request start, so ini_set() in wp-config.php or functions.php runs too late to matter. The directive has to be raised in a configuration PHP reads before the script, and which one that is depends on how PHP is running.
Where the setting lives
| Hosting setup | Where to set it |
|---|---|
| Shared hosting with a control panel | The panel's PHP settings or "Select PHP Version" screen |
| PHP-FPM (most modern hosts, nginx, managed WordPress) | php.ini for the pool, or a .user.ini in the site root |
| Apache with mod_php | .htaccess with php_value upload_max_filesize 64M |
| Docker or your own server | The container's php.ini or a conf.d override, then restart PHP |
| Managed WordPress hosts | Often fixed; ask support, or use their config option |
The .user.ini route works on PHP-FPM and CGI setups and is the most portable:
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
max_execution_time = 300
PHP-FPM caches .user.ini for five minutes by default, so a change appears after that interval rather than immediately. On Apache with mod_php the same values go in .htaccess as php_value lines — but on PHP-FPM those lines cause a 500 error, because Apache does not recognise them without mod_php. If the site breaks the moment you add them, that is the diagnosis; remove them and use .user.ini. The rest of the file is described in the default .htaccess.
The limits behind the limit
Raising upload_max_filesize alone is the most common half-fix. Three more values participate:
post_max_sizecaps the whole request body. Set it equal to or larger than the upload limit, or PHP drops the entire POST and WordPress reports nothing or a blank page.memory_limitmust be large enough to process the file once it is on disk; image uploads generate several resized copies in memory. Keeping it abovepost_max_sizeis the PHP manual's rule of thumb rather than a hard mechanism, and the same setting is covered in raising the memory limit.- The web server's body limit. Nginx's
client_max_body_sizedefaults to 1 MB and returns a 413 before PHP is involved. Apache'sLimitRequestBodydoes the same when set. A 413 after fixing PHP means this layer.
Order them: web server ≥ post_max_size ≥ upload_max_filesize, with memory_limit above post_max_size.
Confirming the change took effect
Media › Add New prints the current maximum, and Site Health › Info › Media Handling lists the PHP values WordPress sees. If the number did not change after editing a file, the file is not the one PHP reads: run php --ini on the command line to list loaded files, remembering that the CLI and the web server can use different php.ini files. A phpinfo() page is the definitive answer for the web context, and should be deleted after use.
Multisite
On a network, Network Admin › Settings has "Max upload file size" in kilobytes, which caps uploads below the PHP limit for every site. A network where PHP allows 64 MB and the setting reads 1500 still refuses anything over 1.5 MB, with a different message. Raise both.
When the file should be smaller instead
A 40 MB image is a problem the upload limit does not solve; it becomes a 40 MB page. For images, resizing before upload or optimising them is the fix. For video, a hosting provider or an external service and an embed. For a large theme or plugin zip, the limit is the right tool, and so is uploading over SFTP and activating from the admin, which bypasses the limit entirely.
Verify
- Media › Add New shows the new maximum.
- Upload a file just under it: it succeeds.
- Upload a file larger than
post_max_size: PHP drops the whole request and WordPress typically answers "The link you followed has expired", because the form's security field was dropped with it. Seeing that for a file underupload_max_filesizemeans the two values are in the wrong order. - On nginx, upload a file over the old
client_max_body_size: no 413.
Frequently asked
- upload_max_filesize is a PHP_INI_PERDIR directive: it is fixed when the request starts and cannot be changed by a running script. It must be set in php.ini, .user.ini, the host's PHP settings panel, or an Apache .htaccess on servers running mod_php.
- post_max_size caps the whole request and must be at least as large as upload_max_filesize, or the upload is dropped silently. A 413 is the web server's own body-size limit, client_max_body_size on nginx, which sits in front of PHP.
- Media › Add New prints 'Maximum upload file size' and Tools › Site Health › Info › Media Handling lists upload_max_filesize and post_max_size. Both read the live PHP values, so they confirm whether a change took effect.