Fix “Unable to Create Directory wp-content/uploads” in WordPress

A stylized folder icon with a create-directory plus sign crossed out by an error mark. Text: FIX UPLOADS FOLDER ERROR.

We may earn a referral fee at no additional cost to you when you shop through the links on this page.

If WordPress refuses to upload media with “Unable to create directory wp-content/uploads” or “The uploaded file could not be moved”, the cause is almost always the same: the wp-content/uploads directory is not writable by the user your web server runs as. This DevAnswers guide fixes it both ways: a few terminal commands if you have SSH, and a File Manager or SFTP method if you do not.

Fix It With SSH (Self-Managed Server) 

If you manage your own server or VPS and can open a terminal, this is the complete fix. (No SSH access? Skip to the File Manager method below.) WordPress writes uploads as the user your web server (PHP) runs as, so give that user ownership of the WordPress files and set sane permissions. On Debian and Ubuntu the web server runs as www-data:

Terminal
# Replace /var/www/html with your WordPress path
sudo chown -R www-data:www-data /var/www/html/wp-content

Then set directories to 755 and files to 644 (the permissions WordPress recommends):

Terminal
sudo find /var/www/html/wp-content -type d -exec chmod 755 {} \;
sudo find /var/www/html/wp-content -type f -exec chmod 644 {} \;

That is usually all it takes. Reload your Media Library and try the upload again. The real fix here is correct ownership (the chown step), not loosened permissions, so never reach for chmod 777. On RHEL, Rocky, AlmaLinux, or Fedora, the web server user is apache instead, so use sudo chown -R apache:apache /var/www/html/wp-content; on those systems you may also need the SELinux step below.

RHEL and Rocky: Set the SELinux Context 

On Red Hat based systems with SELinux enforcing, correct ownership and chmod are not enough. SELinux only lets the httpd process write to a directory that carries the httpd_sys_rw_content_t type. Label the uploads directory and apply it:

Terminal
# Make sure the uploads directory exists and is owned by the web server
sudo mkdir -p /var/www/html/wp-content/uploads
sudo chown -R apache:apache /var/www/html/wp-content/uploads
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/wp-content/uploads(/.*)?"
sudo restorecon -Rv /var/www/html/wp-content/uploads

If semanage is missing, install it with sudo dnf install -y policycoreutils-python-utils. After restorecon applies the label, Apache can write to the uploads directory and the error clears. Not sure SELinux is the culprit? getenforce tells you whether it is Enforcing, and a recent denial shows up in the audit log via sudo ausearch -m avc -ts recent (look for an httpd write denial on your uploads path).

On Shared or Managed Hosting (No SSH) 

Most WordPress sites run on shared or managed hosting where you cannot open a terminal, and often cannot change file ownership yourself because the host controls it. You have three options, easiest first.

1. Set permissions with an SFTP client (FileZilla). Connect to your site over SFTP, browse to wp-content, right-click the uploads folder and choose File permissions (called File Attributes in some clients). Enter 755, tick Recurse into subdirectories and Apply to directories only, and click OK. Then repeat with 644 and Apply to files only so the folders are 755 and the files are 644.

2. Use your host’s File Manager. cPanel, Plesk and similar control panels include a File Manager where you can select wp-content/uploads, open Permissions, and set it to 755 the same way. Some hosts also provide a one-click Reset Permissions tool for WordPress.

3. Ask your host to fix ownership. If setting permissions to 755 does not clear the error, the problem is file ownership, which only your host can change on a shared server. Open a support ticket and ask them to correct the ownership of your wp-content/uploads directory. On fully managed WordPress hosts (Kinsta, WP Engine, SiteGround and similar) support is usually the fastest fix, since they manage permissions for you.

Whichever method you use, set folders to 755 and files to 644. Never set anything to 777: it lets anyone on the server read, write, and execute your files and is a serious security risk.

Why This Error Happens 

When you upload an image, PHP (running as your web server user) tries to create a dated folder under wp-content/uploads and move the uploaded file into it. If that directory is not owned by or writable by the web server user, both of those operations fail, and WordPress shows one of the two errors above. They are two symptoms of the same root cause: a permissions or ownership mismatch on the uploads directory.

This holds whether you serve WordPress with Apache and mod_php or with nginx and PHP-FPM: in both cases PHP runs as www-data on Debian and Ubuntu, so that is the user that must own the uploads directory. The web server software does not matter here, only the user the PHP process runs as.

WordPress needs write access to the wp-content directory, which contains your uploads, themes, and plugins, to function properly, and the project recommends the standard 755 permission on it. Files and folders typically end up owned by the wrong user after a manual copy, a restore from backup, an scp/rsync as root, or a migration, which is why this often appears right after moving a site. Our guide on when 755 still won’t upload digs into the ownership angle further.

Verify the Upload (and If It Still Fails) 

Re-try a Media Library upload. WordPress should create a dated folder such as wp-content/uploads/2026/06 and write your file there. Confirm the ownership took with:

Terminal
ls -ld /var/www/html/wp-content/uploads
Output
drwxr-xr-x 3 www-data www-data 4096 Jun 14 12:00 /var/www/html/wp-content/uploads

The directory should be owned by your web server user (www-data here). If uploads still fail after fixing ownership, check these:

Disk space. A full disk produces the same symptom. Run df -h and free space if the filesystem is at 100%. Upload path. An incorrect upload_path saved in the database (Settings) can point uploads at a directory that does not exist; clearing it returns WordPress to the default wp-content/uploads. Upload size. If only large files fail, it is a size limit, not permissions: see increasing the PHP upload size.

Summary 

The WordPress “unable to create directory” and “uploaded file could not be moved” errors come down to the wp-content/uploads directory not being writable by your web server user. Fix it by giving that user ownership (www-data on Debian/Ubuntu, apache on RHEL/Rocky) and setting 755 on directories and 644 on files, never 777. On RHEL with SELinux, add the httpd_sys_rw_content_t context. If it persists, check disk space and the configured upload path.

Support DevAnswers
Written, tested and maintained by one developer. Your support keeps these guides accurate and ad-light.
Buy me a coffee

4 replies

Leave a reply

  1. Jomar Milan

    Hey, thanks for this! I’m trying to set up WordPress self-hosted, and I guess I forgot to set up folder permissions. Unfortunately, I ran into a problem, since it’s asking me for FTP/SFTP credentials. I do use SFTP sometimes, but I use SSH key authentication instead of password authentication for security. Unfortunately, it doesn’t seem like this is an option… What do I do?

    1. Jack

      I’m not sure exactly where you were seeing the prompt for SFTP credentials, but some general information might help you.

      Do you know the password of your ‘root’ user account, or an admin account you set up on the server? The credentials for one of those accounts should get you in if you’re being prompted for credentials when logging in via SSH.

      Even if you have a key pair set up on the server, you’ll need to know the password for ‘root’ or your admin account once you start connecting to the server. If you’re on Windows, you can use Putty to set your connection up to automatically provide the ‘root’ username and password each time you connect, making it seem like you don’t need the SFTP credentials, for example: https://www.digitalocean.com/community/tutorials/how-to-use-pageant-to-streamline-ssh-key-authentication-with-putty

      But, in a nutshell, that’s what SFTP is. Your SSH keypair, followed by logging in with an account on the server, whether that be ‘root’ or another admin account.

  2. NadVS

    Hello, I wanted to make this command sudo, but it’s not recognized. And I don’t have root access because I am on a shared hosting. What should I do in this situation? Thank you

    1. DevAnswers

      Does the uploads folder exist? Can you write to it via FTP?