You drag a photo into the WordPress media library, the progress bar creeps forward, and then it stalls with a vague red line: "HTTP error." No file name, no code, nothing to Google that points at a real fix. Sometimes it's worse — the upload finishes but the image never shows up, or you get "Unable to create directory wp-content/uploads/2026/07. Is its parent directory writable by the server?" We see tickets like this every week, and the cause is almost always one of a handful of usual suspects. Here's how to find yours.
The Symptom, in Its Different Flavors
Not every upload failure looks the same, and the exact wording is a useful clue:
- "HTTP error" during upload, no other detail — usually a server-side limit or a timeout, not a WordPress bug.
- "Unable to create directory ... Is its parent directory writable by the server?" — a permissions or ownership problem on
wp-content/uploads. - Upload bar stuck at 0% or fails instantly — often a security plugin or mod_security rule blocking the POST request before PHP even sees it.
- "The uploaded file exceeds the upload_max_filesize directive in php.ini" — self-explanatory, but the fix isn't always where people look first.
- Large images (5000px+ camera photos, big PNGs) specifically fail while small ones work fine — almost always memory_limit or a missing/misconfigured image library (GD or Imagick).
What's Actually Causing It
Strip away the different error messages and it comes down to a short list of things that can go wrong between your browser and the disk on the server:
- PHP upload limits are too low.
upload_max_filesizeandpost_max_sizecap how big a single file (or the whole form submission) can be. Shared hosting defaults are often 8–32MB, which modern phone camera photos blow past easily. - PHP memory or execution time runs out mid-upload. WordPress resizes the original into several thumbnail sizes right after upload. A large image can exceed
memory_limitor take longer thanmax_execution_time, and the request just dies. - Wrong ownership or permissions on the uploads folder. If
wp-content/uploads(or a dated subfolder inside it) isn't owned by the account the web server runs as, or the permissions are too restrictive, PHP can't write the file even though everything else about the request is fine. - Disk quota is full. cPanel accounts have a set quota. When you hit it, WordPress can still generate a database row for the attachment but the actual file write fails silently.
- A firewall or security plugin is blocking the request. Wordfence, mod_security, or a CDN's WAF can flag large POST requests or certain file types and drop them before WordPress gets involved.
- A stale or conflicting plugin. Older image optimization plugins (WP Smush, EWWW, ShortPixel) sometimes hook into the upload process and choke on specific formats or very large dimensions.
Fix 1: Check and Raise PHP Upload Limits
Start here — it's the fastest to check and the most common cause. Log in to WordPress, go to Media → Add New, and look at the line under the drop zone: "Maximum upload file size: XX MB." That number tells you what PHP is currently allowing.
If it's lower than you need, raise it in cPanel rather than guessing at a .htaccess edit:
- In cPanel, open MultiPHP INI Editor.
- Select your domain, switch to Editor Mode.
- Set:
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
max_execution_time = 300
max_input_time = 300
Save, then reload the Add New Media screen — the "Maximum upload file size" line should update immediately. If it doesn't, your host may be applying a hard cap at the server level; that's when you open a ticket rather than fight it in wp-config.php.
If you don't have MultiPHP INI Editor access (some reseller or restricted accounts don't), the fallback is adding this to wp-config.php, above the "That's all, stop editing!" line:
@ini_set('upload_max_size', '64M');
@ini_set('post_max_size', '64M');
@ini_set('memory_limit', '256M');
This only works if PHP is running as an Apache module or in a mode that allows runtime overrides — on many modern setups (PHP-FPM), it's silently ignored, which is why the cPanel route is more reliable.
Fix 2: Correct Permissions on wp-content/uploads
If you're seeing "Unable to create directory" or "is not writable," this is your problem. Connect over SSH or use File Manager, and check ownership first:
ls -la wp-content/ | grep uploads
The uploads folder should be owned by your cPanel account's user, not root or a different user (this happens after some restores or migrations that ran as root). Fix ownership and permissions together:
chown -R youruser:youruser wp-content/uploads
find wp-content/uploads -type d -exec chmod 755 {} \;
find wp-content/uploads -type f -exec chmod 644 {} \;
Replace youruser with your actual cPanel username — check it with whoami if you're unsure. Avoid the temptation to chmod -R 777 the folder "just to make it work." It will work, but it also means any script on the account (or a compromised neighbor on shared hosting, in rare misconfigurations) can write to it. 755 for directories and 644 for files is the correct, safe combination for almost every setup.
Fix 3: Check Disk Quota
A full quota is an easy one to miss because the error it produces doesn't mention "disk" or "quota" at all — you just get a generic HTTP error or a broken thumbnail. Check it in cPanel under Statistics or run:
df -h
quota -s
If you're at or near 100%, clear space before doing anything else: old backup archives in public_html, unused plugin/theme zip files, or bloated log files (error_log can quietly grow to gigabytes on a busy site) are the usual culprits. On a VPS, also check /tmp — PHP sometimes stages uploads there before moving them, and a full /tmp partition breaks uploads even when your account's own quota looks fine.
Fix 4: Rule Out mod_security and Security Plugins
If small uploads work but the request fails instantly (not after a delay) regardless of size, a firewall rule is a likely cause. In cPanel, look for ModSecurity under Security, open it for your domain, and check the audit log around the time of your failed upload for a blocked rule ID. You can disable ModSecurity for that one domain temporarily to confirm, then ask your host to add a targeted exception instead of leaving it off.
On the plugin side, temporarily deactivate any security plugin (Wordfence, Sucuri, All In One WP Security) and retry the upload. If it works, go back into that plugin's firewall settings and look for options related to file uploads or "block requests with unusual content" — that's usually the switch causing it.
Quick Reference
| Symptom | Most Likely Cause | Where to Fix |
|---|---|---|
| Generic "HTTP error" | PHP limit or timeout | MultiPHP INI Editor |
| "Unable to create directory" | Ownership/permissions | SSH / File Manager |
| Fails instantly, every file | Firewall / security plugin | ModSecurity, plugin settings |
| Only large images fail | memory_limit too low | MultiPHP INI Editor |
| Works, but file never appears | Disk quota full | cPanel Statistics, df -h |
Prevention
Once it's fixed, a few habits keep it from coming back:
- Resize large camera photos before uploading, or install an image optimization plugin that compresses on upload — it reduces load on PHP's memory and speeds up your site as a bonus.
- Set a calendar reminder to check disk usage monthly if you're anywhere near your quota, rather than finding out from a failed upload.
- Keep a note of your working PHP limits so a hosting migration or PHP version change doesn't quietly reset them.
- Avoid plugins that haven't been updated in over a year, especially ones that hook into the media upload process.
Frequently Asked Questions
Why does the upload work for small images but fail for large ones?
This points at memory_limit or max_execution_time rather than upload_max_filesize. WordPress generates several resized copies right after upload, and that step is what runs out of memory or time on bigger originals — the initial file transfer itself usually succeeds.
I raised the PHP limits in cPanel but the "Maximum upload file size" text still shows the old number. Why?
Your host may be enforcing a hard ceiling at the server or PHP-FPM pool level that overrides per-account settings, or you're editing the wrong PHP version if your site runs on a different one than the editor defaulted to. Confirm the active PHP version under MultiPHP Manager first, then re-check the INI editor for that specific version.
Is it safe to set the uploads folder permissions to 777?
No. 777 makes the folder writable by any process on the server, not just your site, which is an unnecessary risk on shared hosting. 755 for directories and 644 for files gives PHP everything it needs to write files without opening that door.
Can a CDN or Cloudflare cause upload failures?
Yes, if a WAF rule or upload size limit on the CDN's proxy layer is lower than your origin server's PHP limits. If uploads fail from outside but work fine when you temporarily bypass the CDN (or test from an admin IP on its allowlist), the CDN's settings are the place to look.
My upload finished and the thumbnail shows a broken image icon. What's wrong?
That's usually a missing or misconfigured image library, not an upload problem at all — the file saved, but WordPress couldn't generate the resized versions. Check under Tools → Site Health → Info → Media Handling to confirm GD or Imagick is active, and ask your host to enable one if both show missing.
