WordPress Media Library Not Uploading Images? The Real Fix
You drag a JPEG into the Media Library, the progress bar creeps to 100%, and then... nothing. Or worse, you get a red "HTTP error" with no other detail. It's one of the most common WordPress complaints we see, and almost every case traces back to one of five things: folder permissions, a low PHP memory limit, a full disk, a misbehaving plugin, or a security rule blocking the request. Let's go through each one in order, starting with the fastest checks first.
Symptom: what a broken media upload actually looks like
Media upload failures show up in a few different flavors, and the exact wording is a clue in itself:
- "HTTP error" right after the upload bar finishes — usually a server-side crash (memory, disk, or a plugin hook) rather than a network issue.
- "Unable to create directory wp-content/uploads/2026/08. Is its parent directory writable by the server?" — a permissions problem, almost always.
- The file uploads but the thumbnail is broken or missing — usually a memory limit hit during image resizing (GD or Imagick), not the upload itself.
- Upload just hangs at a fixed percentage forever — often a proxy or WAF (ModSecurity, Cloudflare) silently dropping the request.
- "The uploaded file exceeds the upload_max_filesize directive" — self-explanatory, but the fix trips people up because two different PHP settings control it.
Open your browser's dev tools (F12 → Network tab) and try the upload again. Click the failed async-upload.php request and check the response — it often has a real PHP error buried in it even when the WordPress UI just says "HTTP error."
Cause 1: wp-content/uploads has the wrong ownership or permissions
This is the single most common cause, especially right after a migration, a restore from backup, or moving a site between hosts. The web server process needs write access to the uploads folder, but the files often end up owned by the wrong user or locked down too tight.
Fix it over SSH
cd /home/youruser/public_html/wp-content
find uploads -type d -exec chmod 755 {} \;
find uploads -type f -exec chmod 644 {} \;
chown -R youruser:youruser uploads
On cPanel accounts, the folder owner should match your cPanel username — not root, not nobody. If you're not sure what it should be, check ownership on a folder you know works correctly (like wp-content/themes) and match it:
ls -la wp-content/ | grep themes
No SSH access? Do the same thing in cPanel's File Manager: right-click uploads → Permissions → set folders to 755 and files to 644, and tick "Recurse into subdirectories."
Cause 2: PHP memory limit is too low for image processing
Uploading a file and processing it are two separate steps. WordPress generates several resized copies (thumbnail, medium, large, and whatever your theme adds) using GD or Imagick, and that resizing step is memory-hungry — especially for large JPEGs or PNGs straight off a modern phone camera (12+ MP originals are routine now).
If PHP runs out of memory mid-resize, the original file may upload but the thumbnails fail silently, or the whole request dies with a 500.
Check and raise the limit
In cPanel, go to MultiPHP INI Editor and bump these values for the domain:
| Setting | Typical default | Recommended |
|---|---|---|
| memory_limit | 128M | 256M |
| upload_max_filesize | 32M or 64M | 64M (or higher for large media) |
| post_max_size | 32M | Must be ≥ upload_max_filesize |
| max_execution_time | 30 | 120 |
That last row matters more than people expect — a large image that needs several resized versions generated can simply take longer than 30 seconds on a busy shared box, and the request gets killed before it finishes.
No MultiPHP INI Editor (unmanaged VPS)? Edit your PHP-FPM pool config or php.ini directly, then reload PHP-FPM:
sudo nano /etc/php/8.2/fpm/pool.d/www.conf
# php_admin_value[memory_limit] = 256M
sudo systemctl reload php8.2-fpm
Cause 3: the disk (or your cPanel quota) is actually full
WordPress's "unable to create directory" error is misleading — it fires for a genuinely full disk just as often as for a permissions problem, because the server can't write a new folder either way. Check this before you spend twenty minutes chasing permissions.
df -h
du -sh /home/youruser/public_html/wp-content/uploads
On shared cPanel hosting, check your quota from the main cPanel dashboard — it's usually shown right on the front page as a percentage. If you're at 100%, WordPress can't write anything new anywhere, including cache files, session data, or new upload folders, even though existing pages still load fine from cache.
Common disk hogs worth checking first: old Softaculous or plugin auto-backups sitting in wp-content/backups, bloated wp-content/cache directories, and orphaned image sizes from a theme change (regenerate-thumbnails plugins can leave huge numbers of unused files behind).
Cause 4: a security plugin or server-level firewall is blocking the request
If uploads work for small files but fail for anything above a certain size or with certain filenames, look at ModSecurity or your WAF next. Some rulesets flag multipart form uploads that look unusual — long filenames, uncommon characters, or files uploaded via certain plugins that don't set standard headers.
Check the Apache error log or ModSecurity audit log for the exact request:
tail -100 /home/youruser/logs/domain.com/error_log
# or, if you have WHM access:
grep "async-upload" /usr/local/apache/logs/error_log
If you see a ModSecurity rule ID in there, you (or your host) can whitelist that specific rule for the /wp-admin/async-upload.php path rather than disabling ModSecurity entirely — turning it off site-wide trades one problem for a much bigger one.
Also worth a quick test: temporarily deactivate security plugins like Wordfence or All In One WP Security and retry the upload. If it suddenly works, the plugin's upload scanning is the culprit, and you can adjust its file-scan settings instead of leaving it off.
Cause 5: a plugin or theme is hooking into the upload process and failing
Image optimization plugins (Smush, ShortPixel, Imagify), CDN plugins that try to offload media immediately, and some page builders all hook into wp_handle_upload. If one of them throws a PHP fatal error, the whole upload can fail even though the core WordPress logic is fine.
Enable debug logging to catch it:
// in wp-config.php, above "That's all, stop editing!"
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
Retry the upload, then check wp-content/debug.log for a fatal error with a plugin name in the stack trace. Deactivate that plugin, confirm uploads work again, then update it or find an alternative — most of these issues get fixed within a release or two of the plugin catching up to a PHP version bump.
Prevention
- Set
memory_limitto at least 256M for any site handling regular media uploads — 128M is fine for a brochure site, not for a photography portfolio or WooCommerce store with product galleries. - Resize large images before upload where you can — a 4000px-wide camera original doesn't need to be full-size on a website anyway, and it saves both processing time and disk space.
- Watch your disk quota, not just after something breaks. cPanel can email you at 80%/90% usage — turn that on under Notifications if it isn't already.
- Keep image optimization and CDN plugins updated, and test uploads after any major plugin update on a staging copy first.
- If you migrated or restored the site recently, always run a permissions fix pass on
wp-content/uploadsas a standard step, not just when someone reports a broken upload.
Quick diagnosis checklist
| What you see | Most likely cause |
|---|---|
| "Unable to create directory..." | Permissions or full disk |
| Generic "HTTP error" after 100% | Memory limit or execution timeout |
| File uploads, thumbnails missing/broken | GD/Imagick out of memory |
| Upload hangs, never completes | WAF/ModSecurity or proxy timeout |
| Works for small files, fails on large ones | upload_max_filesize / post_max_size mismatch |
| Fails only with certain plugins active | Plugin hook throwing a fatal error |
Frequently asked questions
Why does WordPress say the upload succeeded but the image doesn't show up?
That's usually a thumbnail generation failure, not an upload failure — the original file made it to the server, but GD or Imagick ran out of memory while creating the resized versions. Raise memory_limit to 256M and try the Regenerate Thumbnails plugin on that file to confirm.
I fixed the permissions but uploads still fail. What now?
Confirm the disk quota isn't full (df -h or your cPanel usage bar) and check wp-content/debug.log for a plugin fatal error. Those two get missed most often after permissions are already correct.
Can I just set folder permissions to 777 to make it work?
Don't. 777 makes wp-content/uploads world-writable, which is a common entry point for malware uploads disguised as images. Use 755 for folders and 644 for files, and match ownership to your hosting account's actual user instead.
Where do I change upload_max_filesize if I'm on Getwebup managed hosting?
Use cPanel's MultiPHP INI Editor — select your domain, raise upload_max_filesize and post_max_size together (post_max_size must be equal to or larger than upload_max_filesize), and save. No server restart needed.
Is it normal for large batches of images to fail even after these fixes?
Bulk uploads of 20+ images at once can still hit max_execution_time even with a generous memory_limit, because each image's processing time adds up in one request. Upload in smaller batches of 5-10, or raise max_execution_time to 300 temporarily for a big import.