The uploaded file exceeds the upload_max_filesize directive
PHP refused the file before WordPress saw a byte of it. The number in the message is PHP's ceiling, not WordPress's.
The uploaded file exceeds the upload_max_filesize directive in php.ini.
Four separate limits can produce this, and raising the wrong one changes nothing. Print what PHP currently reports for upload_max_filesize and post_max_size, compare both against your file, and remember post_max_size must be the larger of the two or the upload fails silently instead.
What causes it, most likely first.
Work down the list. Each check is written to rule its row in or out before you change anything, because the fixes below it are different and a guess costs more than a command.
| Cause | How to check | Fix |
|---|---|---|
| upload_max_filesize is below the file size | Media → Add New prints the effective maximum under the drop zone. If that number is smaller than the file, this is the one. | Raise upload_max_filesize in the PHP configuration that actually loads. A value in a php.ini the process does not read is the usual reason an edit appears to do nothing. |
| post_max_size is smaller than upload_max_filesize | The upload fails with an empty $_FILES array rather than this message, or the admin screen reloads with no error at all. | Set post_max_size above upload_max_filesize. PHP discards the whole request body first, so a generous file limit behind a small body limit never gets consulted. |
| The web server caps the request before PHP runs | The browser shows a 413 from nginx or Apache rather than a WordPress screen. Nothing appears in the PHP log because PHP was never reached. | Raise client_max_body_size in nginx, or LimitRequestBody in Apache, to at least the PHP value. This limit is enforced on Content-Length, so it rejects the request before any of it is buffered. |
| A multisite network limit | Network Admin → Settings has a “Max upload file size” field in kilobytes, and it is lower than the PHP limit. | Raise the network setting. It is applied per site regardless of what PHP allows, and it is measured in KB while every other limit here is in MB. |
Fixing it, step by step.
Commands assume WP-CLI and shell access. Where you have neither, each step says what it is doing so it can be done from the dashboard or over SFTP instead.
Ask PHP what it is enforcing, from inside WordPress
The value that matters is the one the running process has, which is not necessarily the one in the php.ini you edited.
wp eval 'echo ini_get("upload_max_filesize"), " / ", ini_get("post_max_size"), PHP_EOL;'Find which php.ini that process actually loads
A stack can have several. Only the loaded one has any effect, and the path is printed for you.
php --ini | head -n 3
Raise both values, keeping post_max_size larger
Set them together. Raising one without the other is the most common way this gets half-fixed.
upload_max_filesize = 256M post_max_size = 320M memory_limit = 512M
Raise the web server limit to match
PHP never sees a request the web server already rejected, so this has to move too.
# nginx client_max_body_size 320m; # then nginx -t && systemctl reload nginx
Confirm the new ceiling is live
Re-read it from WordPress rather than trusting the file. If it has not changed, PHP-FPM has not been reloaded.
systemctl reload php*-fpm wp eval 'echo ini_get("upload_max_filesize"), PHP_EOL;'
What the platform takes off the list.
The four limits are set together here rather than one at a time, and nginx is deliberately configured above every value the PHP Settings screen can produce — so the limit you can see and change in the dashboard is the one that actually applies, instead of a smaller web-server cap silently overriding it. Changing it is a form field, not an edit to a file whose location you have to work out first.
Questions, answered.
I raised upload_max_filesize and nothing changed. Why?
What is the difference between this and “failed to write file to disk”?
Is there a maximum I should not go past?
Can I raise the limit for one site on a multisite network only?
If that was not it.
These fail in ways that look similar from the browser.