Troubleshooting guide · wordpress · Published 2026-08-15 · 4 min read
WordPress media uploads failing
Why WordPress media uploads fail with an HTTP error, and the ordered fixes for uploads permissions, PHP upload_max_filesize, execution time and disk space.
- ·HTTP error
- ·Permissions
- ·Limits and space
Symptoms
You drag an image into the media library and it fails. Depending on the browser the failure shows as "HTTP error" with no detail, a blank upload box, a "Sorry, uploaded file exceeds the maximum upload size" line, or the file appears small and then vanishes. PHP intentionally hides the real reason from the browser, so the message is a hint, not the diagnosis. The same file can upload to a different site or over a different path and succeed, which shrinks the cause list to your server settings.
Common causes
wp-content/uploadsis not writable by the web server user, so the file arrives at PHP, PHP cannot save it, and the answer is an HTTP error.- PHP limits:
upload_max_filesizebelow the file size. A 2 MB photo fails because the cap is 1 MB. post_max_sizeis small too, or the request dies on the combined limit.- Execution time is too short; image processing for large files, especially with a plugin that recompresses on upload, times out mid-save.
- Memory: resizing and image-quality steps can hit the memory cap addressed in how to raise the WordPress memory limit.
- The disk is full. WordPress saves, fails to move or resize, and reports a 500 or an HTTP error.
- A security plugin or the host's Web Application Firewall blocks the
multipart/form-dataPOST. - The media library's REST upload path is blocked. The library saves files over the WordPress REST API with an
application/jsonrequest, not a plain form POST, so a security plugin, WAF rule, or browser add-on that interceptsapplication/jsonresponses (or thewp/v2/mediaroute itself) can fail the upload even when the classic form path works. Check for a console message naming the failed REST request before chasing disk or PHP settings.
The fix in order
- Prove the simplest request works first. Upload a tiny file (a 1 x 1 PNG). If that succeeds and a large one fails, it is a size limit or time; if even the tiny file fails, it is a server-side block or permission. This one test splits the diagnosis in half.
- Check the uploads directory permissions.
ls -ld wp-content wp-content/uploads
drwxrwxr-x www-data www-data ...
The directory must be owned by and writable to the web server user. The web user differs from your shell user on many hosts; if ls shows the directory owned by www-data and your shell writes as root, that is the mismatch. Set the user and mode via the host tool or:
chown -R www-data:www-data wp-content/uploads
chmod -R 755 wp-content/uploads
Keep uploads recursive-writable for the web user, but never world-writable.
- Raise the PHP upload limits. The relevant php.ini pair:
upload_max_filesize = 16M
post_max_size = 20M
Site Health and the host panel show the current values. After editing, restart PHP-FPM or Apache, because the value is read at startup. Then the media library shows the new cap.
- Give image editing time and memory. For big panoramas or batch image operations, images get processed server-side after save. If a 12 MB photo consistently fails while a 2 MB one works, raise
max_execution_timeto 120 and the memory limit per the memory-limit path, or generate derivatives in a queue. - Free disk space. A full volume behaves as a permission or 500 kind of error. Confirm with
df -h, then empty log files, old backups, andwp-content/cache. - Test around plugins and WAF. Temporarily deactivate the security plugin and the image-optimisation plugin (if stacking causes double-processing). Many such plugins queue a WebP or compression step that runs after the upload and turns a fine request into a 500. If the area is behind a proxy, check that the host WAF is not dropping POST bodies above a size.
- Try the alternate upload path. On a shared host where
uploadssits on a flaky mount, moving the upload folder to object storage via theupload_pathandupload_url_pathsettings, or a plugin that delegates to a CDN, sidesteps the filesystem entirely. That is a deeper redesign, only worth it when the disk itself is the recurring offender.
Prevention
- Set upload limits to the largest legitimate asset plus headroom, and keep the media library at 2 MB to 10 MB by default.
- Store the uploads user and mode in the deploy doc; a fresh server reproduces the working setup in one line.
- Watch the disk: an alert at 90% full is into a failed upload sooner than a server view.
- Prefer one image plugin in the queue, not several compression passes, so the after-upload step is easy to blame, covered in the image-optimisation plugin comparisons.