Fig2WP Logo Fig2WP Image Uploader
A glass panel hovering above an open metal tray, cracked where it struck instead of dropping in

Published August 16, 2026 · 5 min read · by the Fig2WP team

"The Uploaded File Could Not Be Moved to wp-content/uploads" — What to Check

The file reached the server and failed on the last step: copying it out of PHP's temp directory into the uploads folder. That folder exists — so this is about writing into it, not creating it. Check account disk quota first, then ownership.

Quota goes first because it's the one that lies to you. df -h can show 60% free while your hosting account is at its limit, and every permissions check you run afterwards will come back clean.

If your message names a folder WordPress couldn't create — "Unable to create directory wp-content/uploads/2026/08" — you're in the neighbouring problem, and that one has its own guide. The two look similar and fail at different moments, which is worth keeping straight before you start changing things.

Which stage this is

An upload passes through four hands:

  1. PHP receives the file and writes it to a temp directory. Failing here gives you "Missing a temporary folder".
  2. WordPress checks the type against its allowlist. Failing here gives you "not permitted for security reasons".
  3. WordPress moves the temp file into wp-content/uploads/YYYY/MM. This message is a failure here.
  4. WordPress scales the image and builds thumbnails. Failing here gives you "Post-processing of the image failed".

Reaching stage 3 tells you a lot for free: PHP's temp directory works, the file type is accepted, and the destination folder exists. The remaining possibilities are narrow.

Four causes, in checking order

1. The account is out of space

On shared and managed hosting, your account has a quota that has nothing to do with the physical partition. When it's reached, writes fail and the filesystem still looks healthy from the command line.

Check the disk usage figure in your hosting control panel, not df. If it's at the limit, the usual culprits are backup archives inside wp-content, an unrotated debug.log, and years of accumulated -scaled and thumbnail variants. Clearing those buys back a surprising amount.

On a server you control, also run df -i. Inode exhaustion produces identical symptoms while space remains free, and a site with a large file-based cache gets there faster than you'd expect.

2. Wrong ownership on an existing folder

The classic post-migration fault. Restoring a backup over SSH leaves wp-content/uploads owned by root or by your login user, and PHP — running as www-data, apache, or a per-account user — can no longer write into it.

ls -la wp-content/uploads/2026/

Compare the owner against the PHP user. When they differ:

chown -R www-data:www-data wp-content/uploads

Then confirm the mode: 755 on directories, 644 on files. Not 777 — that hands write access to every account on the machine, and it papers over the ownership fault rather than fixing it.

Without root, this is a one-line ticket: "uploads is owned by the wrong user after a restore, please reset ownership to the PHP user."

3. open_basedir confinement

Hardened hosting restricts PHP to a list of allowed paths. If either the temp directory or the uploads directory sits outside that list, the move is refused — permissions immaculate, ownership correct, file still doesn't land.

The tell is in the PHP error log rather than on screen: an open_basedir restriction in effect warning naming both paths. Common on sites served from a symlinked release directory, where the real path differs from the one PHP was told about.

4. The filesystem won't take writes

Containerised deployments mount the application read-only, with uploads expected to be a separate writable volume. If that volume is missing or mounted at the wrong path, every upload fails at this exact step and no permission change makes a difference. SELinux in enforcing mode does the same thing on traditional servers — ls -Z shows the context, and the httpd write boolean is usually what's missing.

Why some files move and others don't

This is the most useful clue in the whole exercise, so it's worth being deliberate about it. Upload a 20 KB PNG and a 4 MB one:

ResultWhat it means
Both failOwnership, open_basedir, or a read-only filesystem. Size is irrelevant to all three.
Small succeeds, large failsA space or quota ceiling. There's room for a little and not for a lot.
Both succeed nowA quota that was cleared, or a transient full disk. Worth finding out which before it recurs.

Cleaning up afterwards

Failed uploads sometimes leave an attachment record behind with no file under it — the Media Library shows a broken thumbnail that resists deletion. Delete those entries once the underlying fault is fixed, then re-upload cleanly. Leaving them creates 404s on any page that referenced them and confuses later debugging.

If the failure caught a batch mid-flight, check which items actually landed before re-running the whole set. Half-uploaded batches are how duplicate media libraries start.

FAQ

What does this message mean?

PHP received your file into its temp directory and the copy into wp-content/uploads failed. The destination folder exists; writing into it is what was blocked.

How is it different from "unable to create directory"?

That message means the month folder couldn't be made at all. This one means it's there and the file couldn't be written into it.

Can a hosting quota cause it?

Yes, and it's easy to miss — an account quota can be full while the partition shows free space. Check the control panel figure, not df.

What permissions should uploads have?

755 on directories, 644 on files, owned by the PHP user. Ownership is what usually breaks; the permission bits often look fine.

Why do small files work and large ones fail?

That pattern points at space or quota. Permission faults don't care how big the file is.

Can open_basedir cause it?

Yes — if either the temp or the uploads directory falls outside PHP's allowed paths, the move is refused despite correct permissions.

Re-running the batch, without the batch

When a server fault eats half an upload, the tedious part is doing the whole set again by hand. Fig2WP sends a Figma selection straight to the Media Library in one press — titles and alt text included — so a re-run costs a click rather than an afternoon.

Get the plugins   Read the bulk upload guide