WooCommerce File Upload Not Working? 9 Fixes That Actually Help
A customer tries to upload their photo, gets an error — or worse, no error — and gives up. If files aren't making it into your WooCommerce orders, the cause is almost always one of nine things.
This guide is ordered by how often each one turns out to be the culprit. Start at the top, and use the diagnosis table to jump straight to your symptom.
Quick answer: the most common cause of failed WooCommerce uploads is a PHP file size limit — shared hosting often caps upload_max_filesize at 2–8 MB, smaller than a typical phone photo. Raise the limit (Fix 1) or use an uploader that bypasses your server entirely.
Table of contents
- Find your symptom
- Fix 1: Raise the PHP upload limits
- Fix 2: Raise the web server's request cap
- Fix 3: Allow the file type in WordPress
- Fix 4: Handle iPhone HEIC photos
- Fix 5: Fix the missing form enctype
- Fix 6: Check folder permissions
- Fix 7: Rule out a plugin or theme conflict
- Fix 8: Check security plugins and firewalls
- Fix 9: Check your upload plugin's own limits
- Common mistakes when debugging
- Frequently asked questions
Find your symptom
| Symptom | Most likely cause | Jump to |
|---|---|---|
| "Exceeded the upload_max_filesize directive" | PHP limit too low | Fix 1 |
| Generic "HTTP error" on larger files only | PHP or server cap | Fix 1, 2 |
| "413 Request Entity Too Large" | nginx/Apache body limit | Fix 2 |
| "Sorry, this file type is not permitted" | WordPress MIME whitelist | Fix 3 |
| iPhone photos rejected, everything else fine | HEIC format | Fix 4 |
| Upload "succeeds" but no file anywhere, no error | Missing form enctype | Fix 5 |
| "Failed to write file to disk" | Folder permissions | Fix 6 |
| Worked last week, broke after an update | Plugin/theme conflict | Fix 7 |
| Fails only for some users or file names | Firewall / security rules | Fix 8 |
| Plugin says limit reached or file too small | Plugin's own settings | Fix 9 |
Fix 1: Raise the PHP upload limits
PHP enforces its own file size ceiling before WordPress or WooCommerce ever sees the file. On shared hosting it's often just 2–8 MB — and modern phone photos run 3–10 MB. That mismatch is the single biggest source of "random" upload failures.
Check your current limit in WordPress admin → Tools → Site Health → Info → Media Handling, or with:
<?php echo ini_get( 'upload_max_filesize' ); ?>
Three values matter, and they must line up:
upload_max_filesize— max size of one uploaded filepost_max_size— max size of the whole request (must be ≥ upload size)max_execution_time— slow uploads on big files can hit this too
If your host gives you a php.ini (or a MultiPHP/PHP options panel in cPanel):
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 300
Via .htaccess (Apache with mod_php only):
php_value upload_max_filesize 64M
php_value post_max_size 64M
Via wp-config.php — note this raises WordPress's memory, not the upload limit; it's listed because tutorials keep recommending it as if it did:
define( 'WP_MEMORY_LIMIT', '256M' ); // helps processing, not upload caps
If none of these stick, your host locks PHP settings — open a support ticket and ask for the values directly. On managed hosts that's usually a five-minute change.
[Screenshot placeholder — ALT: "Site Health Info screen showing the max upload file size value"]
Fix 2: Raise the web server's request cap
Even with PHP configured, the web server itself can reject large requests before PHP runs. The telltale sign is a 413 Request Entity Too Large error.
nginx — add to your server block and reload:
client_max_body_size 64M;
Apache — check for a restrictive LimitRequestBody in your config or .htaccess:
LimitRequestBody 67108864
On managed WordPress hosting you usually can't edit these yourself — but support can, and "please set client_max_body_size to 64M" is a request they see daily. Cloudflare's free plan also caps uploads at 100 MB, which only matters for video and raw design files.
Fix 3: Allow the file type in WordPress
WordPress keeps a whitelist of allowed MIME types. Anything outside it gets "Sorry, this file type is not permitted for security reasons." Common casualties: SVG, AI, EPS, and sometimes PSD — exactly the formats design customers send.
Extend the whitelist deliberately, one type at a time:
add_filter( 'upload_mimes', function ( $mimes ) {
$mimes['ai'] = 'application/postscript';
$mimes['eps'] = 'application/postscript';
$mimes['psd'] = 'image/vnd.adobe.photoshop';
return $mimes;
} );
A deliberate warning about SVG: it's an XML format that can carry scripts, making it a real XSS vector. Don't enable SVG uploads from customers unless the files are sanitized on arrival — accept PDF or EPS instead, or use an upload service that processes files off your server.
Fix 4: Handle iPhone HEIC photos
iPhones save photos as HEIC by default. If your store rejects HEIC, you're rejecting a large share of phone-camera customers — and they usually won't tell you; they'll just leave.
Your options, in order of effort:
- Accept HEIC and convert server-side. WordPress 6.7+ converts HEIC on upload if your server's ImageMagick build supports it (many don't — check Site Health).
- Add
image/heicto allowed MIME types (Fix 3 pattern) and convert during production instead. - Use an uploader with built-in conversion. Our File Uploader for WooCommerce accepts HEIC out of the box on every plan and handles conversion on the CDN side, so it never depends on your server's image libraries.
Whatever you pick, test with a real iPhone photo — not a renamed JPG.
Fix 5: Fix the missing form enctype
This one produces the most confusing symptom: the form submits fine, no error appears, but the file simply doesn't exist server-side.
HTML forms only transmit files when the form tag includes enctype="multipart/form-data" — and WooCommerce's add-to-cart form doesn't include it by default. Any custom-coded upload field hits this wall.
The fix is a one-liner in JavaScript:
document.querySelectorAll( 'form.cart' ).forEach( function ( form ) {
form.setAttribute( 'enctype', 'multipart/form-data' );
} );
If you're running custom upload code, our full code tutorial covers this and the other traps in that build.
Fix 6: Check folder permissions
"The uploaded file could not be moved" or "Failed to write file to disk" means PHP can't write into wp-content/uploads. It usually appears after a migration or a botched permissions "hardening."
Correct values: directories 755, files 644, with the uploads tree owned by the web server user. Via SSH:
find wp-content/uploads -type d -exec chmod 755 {} \;
find wp-content/uploads -type f -exec chmod 644 {} \;
Also check that the disk isn't simply full — on small hosting plans, a store collecting customer files hits the quota sooner than you'd think. (That storage creep is one reason CDN-based uploaders exist.)
Fix 7: Rule out a plugin or theme conflict
If uploads worked and then stopped after an update, suspect a conflict. The fast, safe way to test:
- Install the Health Check & Troubleshooting plugin.
- Enter Troubleshooting Mode — it disables plugins only for your session; the live store is unaffected.
- Enable WooCommerce plus your upload mechanism. Test an upload.
- Re-enable other plugins one by one, testing after each, until it breaks.
Nine times out of ten the culprit is an optimization plugin deferring the JavaScript your upload widget needs, or a security plugin (next fix). Also test with a default theme like Storefront — themes that override WooCommerce templates can drop the hooks upload fields rely on.
Fix 8: Check security plugins and firewalls
Security layers love to eat uploads quietly:
- ModSecurity (host-level WAF) blocks requests matching paranoid rules — some file names or contents trigger it, which is why uploads can fail for some customers only. Ask your host to check the ModSecurity log for your domain.
- Wordfence, Sucuri, and similar can block upload endpoints or specific MIME types. Check their live traffic/firewall logs while reproducing the failure.
- Cloudflare WAF rules can challenge or block multipart POSTs. Check the Security Events log, and add an exception for your upload endpoint rather than turning protection off.
The pattern that gives this away: uploads fail intermittently, for certain users, file names, or networks — while your own tests pass every time.
Fix 9: Check your upload plugin's own limits
If you're using a dedicated upload plugin, remember it has its own rules on top of everything above — and those rules produce their own "failures" that are actually settings:
- Monthly upload quotas. Our free plan, for example, includes 500 uploads a month; when a store outgrows that, new uploads pause until the reset (nothing is lost — but it looks like a breakage if you don't know).
- Allowed file types per plan. Image-only plans reject PDFs by design.
- Minimum image resolution rules you set for print quality will reject small files — correctly, but check the customer-facing message says why.
Before debugging servers for an hour, open the plugin's settings and logs. The answer is often a checkbox.
Common mistakes when debugging
Testing only from your desktop. Most real customers upload from phones, on mobile networks, with HEIC photos. Reproduce the customer's conditions or you'll chase ghosts.
Changing five things at once. Raise one limit, test, then move on. Otherwise you can't tell which change worked — or which one broke something else.
Editing php.ini values that aren't being read. PHP often loads a different ini file than the one you edited. Confirm with Site Health → Info, not with faith.
Turning off security to "fix" uploads. Add a scoped exception for the upload endpoint instead of disabling your WAF store-wide.
Ignoring the failures you can't see. For every customer who reports a broken upload, several just abandon the order. If uploads matter to your revenue, test the flow monthly — or use upload infrastructure with built-in retries so flaky connections don't turn into lost sales.
Frequently asked questions
Why do WooCommerce uploads fail only on large files?
A size ceiling — PHP's upload_max_filesize/post_max_size (Fix 1) or the web server's request cap (Fix 2). Whichever is lowest wins. Raise them together and retest with a file just above your old limit.
What does "exceeded the upload_max_filesize directive in php.ini" mean?
The file is bigger than PHP's per-file limit. Raise upload_max_filesize and post_max_size in php.ini or your hosting panel — see Fix 1 for exact snippets.
Why does WordPress say "this file type is not permitted for security reasons"?
The file's type isn't on WordPress's MIME whitelist. Add it with the upload_mimes filter (Fix 3) — but avoid enabling SVG from untrusted users, since SVGs can carry scripts.
Why can't my customers upload iPhone photos?
iPhones shoot HEIC by default, and many upload setups only accept JPG/PNG. Either enable HEIC with server-side conversion or use an uploader that accepts and converts HEIC natively (Fix 4).
The upload finishes but the file never appears in the order. Why?
If there's no error at all, check the form's enctype first (Fix 5) — without multipart/form-data, the browser silently drops the file. If the enctype is fine, check whether your upload mechanism actually attaches files to orders or just stores them separately.
Wrapping up
Almost every "broken" WooCommerce upload comes down to a limit (PHP, server, or plugin), a rejected file type (usually HEIC or design formats), or something between the customer and your disk (enctype, permissions, a firewall). Work the table top to bottom and you'll find it.
And if you'd rather never own this class of problem again: File Uploader for WooCommerce sends files from the customer's browser straight to a dedicated upload CDN — no PHP limits, no server caps, no MIME whitelist, HEIC included, with automatic retries on bad connections. The free plan takes ten minutes to try. For choosing an approach from scratch, start with our complete guide to WooCommerce file uploads.