Recommended Free Tools
If media uploads work on your main WordPress site but fail on a subsite, check the subsite’s actual upload directory first. Multisite sites usually write to different paths, and the PHP/web-server account must be able to traverse and write that specific directory. Then check network upload limits, the uploader’s role, and your Apache or Nginx routing. Do not “fix” the problem with chmod 777; WordPress warns that permissions that are too broad can allow attackers to upload malicious files or alter executable code.
Antihost offers managed WordPress hosting with free migration, one-click staging and a 14-day free trial.
What the error usually means
Typical messages include “The uploaded file could not be moved to wp-content/uploads,” “Unable to create directory,” “Sorry, you are not allowed to upload this file type,” or a failed request with an HTTP 403 status. They do not all indicate the same fault.
As an Amazon Associate I earn from qualifying purchases.
- A move, create-directory, or permission-denied message usually means that the account running PHP cannot reach, write to, or rename files in the destination directory.
- A 403 can indicate web-server or security-policy denial before WordPress finishes processing the upload.
- An “invalid file type” message points to a network MIME restriction, not necessarily a filesystem problem.
- An upload that works for the network’s first site but not a subsite often targets a different directory or a different rewrite rule.
WordPress’s file-permissions guidance states: “So if you set the permissions too low, then your server won’t be able to access the file and will cause an error.” The practical implication is to identify the exact site-specific path and PHP execution account before changing anything.
Understand where each Multisite site stores uploads
Multisite does not put every site’s files in one identical directory. The normal layout depends on the site’s position in the network and on whether the network uses the current or legacy storage scheme.
| Network layout | Typical location | What to check |
|---|---|---|
| First site in a modern network | /wp-content/uploads/ |
Confirm the directory exists and is writable by the PHP/web-server account. |
| Later sites in a modern network | /wp-content/uploads/sites/<site-number>/ |
Replace <site-number> with the affected site’s numeric ID; do not assume the main site’s directory is sufficient. |
| Legacy Multisite network | wp-content/blogs.dir/ with files routed through /files/ |
Check both the legacy directory and the rewrite or location rule that serves /files/. |
The site ID is not the same as a username or domain name. In Network Admin, open the Sites list, select the affected site, and note its numeric ID. A subsite with ID 3, for example, commonly uses /wp-content/uploads/sites/3/ in a modern network. A custom upload-path filter, migration, or old installation can change that convention, so verify the path rather than inferring it solely from the ID.
Use a safe diagnostic sequence
Work through these checks in order. Record the exact error, HTTP status, filename, site ID, and time of each test so that a host or administrator can correlate the request with server logs.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
- Reproduce the failure on the affected site. Sign in to the subsite, open Media > Add New, and upload a small image such as a permitted JPEG or PNG. Capture the complete on-screen message and browser-network status.
- Confirm the site and path. In Network Admin > Sites, identify the site ID. Determine whether the network uses modern
uploads/sites/<id>storage or legacyblogs.dir//files/routing. Compare the configured path with the directory that actually exists on disk. - Check the directory and its parents. On the server, inspect the destination and every parent directory. A writable final directory is useless if PHP cannot traverse
/wp-contentor/wp-content/uploads. - Identify the PHP execution account. It may be a PHP-FPM pool user, an Apache worker account, or a host-specific service account. Check the pool or virtual-host configuration rather than assuming a name such as
www-data. - Verify ownership before modes. Make the affected directory owned by the account or group that actually runs PHP, subject to your host’s deployment policy. Correct ownership first; a permissive mode cannot reliably compensate for an incorrect owner, ACL, container mount, or security policy.
- Review upload limits and capabilities. Check Network Admin limits and the uploader’s role before making additional filesystem changes.
- Validate web-server routing. Confirm the Apache or Nginx Multisite rules match the network type and WordPress version.
- Retest with a small allowed image. If it still fails, inspect PHP-FPM, web-server, WordPress, and operating-system security logs for the same timestamp.
Check ownership, traversal, and write access
Inspect without changing anything
From the WordPress document root, inspect the path and each parent directory. Commands such as these provide evidence without altering files:
namei -l /var/www/html/wp-content/uploads/sites/3
ls -ld /var/www/html/wp-content
/var/www/html/wp-content/uploads
/var/www/html/wp-content/uploads/sites
/var/www/html/wp-content/uploads/sites/3
stat /var/www/html/wp-content/uploads/sites/3
Replace the example path with the real document root and site ID. Look for a missing directory, an owner unrelated to the PHP account, a group that the process cannot use, or a parent directory lacking execute (traversal) permission. On systems using ACLs, inspect ACL entries as well as the traditional owner/group/mode fields.
Create the directory only when it is genuinely missing
If the expected directory does not exist, create it through your normal deployment or server-administration process, then assign ownership and access according to the PHP pool and host policy. Do not create a world-writable directory as a shortcut. A migration may also have left the directory on a different volume or container mount; verify that the path belongs to the active web server, not merely to a shell account on another host.
Rank #2
Apply the narrowest workable modes
There is no single safe numeric mode for every hosting stack. A common arrangement is owner and group access for the PHP/web-server account, with directories traversable by the process and files writable only where WordPress needs to create or update them. Some hosts use directory mode 755 and file mode 644; others require group-based 775 because deployments and PHP share a group. Treat those as examples to validate, not universal prescriptions. WordPress specifically warns that overly broad permissions can let an attacker upload malicious files or modify executable code. Never use chmod -R 777 as a blanket repair.
Check Network Admin upload limits and file types
Multisite can reject an upload before WordPress attempts to move it into the destination directory. In Network Admin > Settings, review the network’s maximum upload size and the allowed upload file types. The exact labels can vary by WordPress version, but the settings govern the network rather than one subsite.
- Compare the file size with the network maximum and with PHP limits such as
upload_max_filesizeandpost_max_size. The smallest applicable limit wins. - Check the filename extension and MIME type. A file renamed from one extension to another can still be rejected because its detected type is not allowed.
- Retest with a small, ordinary image after changing a limit. If that succeeds while the original file fails, the directory was probably not the primary fault.
Do not loosen the network’s allowed types merely to bypass a message. Permit only the formats the network’s administrators can safely handle, and investigate unusual MIME reports rather than trusting an extension alone.
Verify the uploader’s role and capabilities
A subsite administrator is not equivalent to the administrator of a single-site WordPress installation. Multisite separates site-level administration from network-wide authority. A user who can manage one site may still be unable to perform an operation reserved for a Super Admin.
WordPress documents the relevant unfiltered-upload rule this way: “With this constant defined, all roles on a single site install can be given the unfiltered_upload capability, but only Super Admins can be given the capability on a Multisite install.” If a workflow requires uploads that bypass normal MIME filtering, review the ALLOW_UNFILTERED_UPLOADS configuration and the Super Admin restriction. Do not weaken filesystem permissions to compensate for a capability decision.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Rank #3
Distinguish a capability failure from a filesystem failure
- If the interface says the file type is not permitted, test the network MIME settings and the user’s capability.
- If the interface says the file cannot be moved or a directory cannot be created, inspect ownership, traversal, storage, and server policy.
- If the same user can upload an ordinary image to one site but not another, compare the two sites’ IDs, paths, and routing rules before changing the role.
Fix Apache Multisite routing
Apache networks depend on mod_rewrite and on override settings that allow the Multisite rewrite rules to operate. If .htaccess is ignored, WordPress may generate URLs that do not map to the stored files, or requests to legacy /files/ paths may return errors.
- Confirm that
mod_rewriteis loaded for the active Apache virtual host. - Check the document root’s
AllowOverridesetting. It must permit the categories of directives used by the network’s.htaccess; a server set toAllowOverride Nonewill ignore them. - Compare the current Multisite rules with the network type: subdirectory and subdomain installations use different rewrite details.
- After changing Apache configuration, reload the service through the host’s approved process and retest both the main site and the affected subsite.
Do not copy rewrite rules from an unrelated network type or an old installation. A rule that appears to fix one URL can break administrator requests or route another site’s files incorrectly.
Fix Nginx Multisite routing
Nginx does not read .htaccess. Every Multisite rewrite and static-file rule must therefore be present in the Nginx server configuration. The correct rules depend on whether the network uses subdomains or subdirectories, whether it is a modern or legacy network, and which WordPress version generated the configuration.
- Confirm that the active
serverblock points to the real WordPress document root. - Install the matching Multisite rules for the network type, including handling for
/files/andblogs.diron legacy networks. - Ensure that the PHP location passes requests to the same PHP-FPM pool whose account owns or can write the upload directory.
- Run the configuration test supplied by your distribution before reloading Nginx, then retest an image upload and its public URL.
An Nginx configuration can allow the upload request to reach PHP while still serving the resulting file from the wrong location. Test both operations: upload the file and open the generated media URL from the subsite.
Handle legacy blogs.dir and /files/ networks
Older Multisite networks may store site files under wp-content/blogs.dir and expose them through /files/ routing. WordPress’s file-permissions guidance specifically notes that a Multisite installation may need the same attention in wp-content/blogs.dir/ as in wp-content/uploads/.
Rank #4
For such a network, check the numeric blog directory, its owner, and the rewrite or Nginx location that maps /files/ to it. A directory that is writable but not routed will produce a different symptom from a directory that PHP cannot write: the upload may complete, yet the image URL returns 404 or 403. Preserve the legacy layout during diagnosis; migrating storage is a separate change that should be planned and tested with backups.
Investigate failures that are not fixed by permissions
Temporary upload directory
PHP first places an upload in its temporary directory before WordPress moves it into the site’s media directory. Check the PHP setting for the temporary upload directory, its existence, free space, ownership, and security policy. A failure there can look like a destination-permission error.
Disk space, inode limits, and quotas
Check free bytes and inodes on the filesystem that contains both the temporary directory and the WordPress directory. Hosting quotas can reject a new file even when Unix permissions look correct.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →SELinux or AppArmor
Mandatory access-control policies can deny writes despite apparently correct owner and mode values. Review audit logs at the time of the failed request and apply the host’s documented policy change rather than disabling the protection globally.
Container and shared-storage mounts
In containers or clustered hosting, the PHP process may see a different mount or UID mapping from the shell session used for inspection. Verify the path from inside the PHP container or the node serving the request, and check shared-storage locking and read/write mounts.
Best Value
Plugins and custom code
A security, media, image-optimization, or storage plugin can filter upload MIME types, alter the upload path, or block requests. Reproduce the issue with such plugins disabled only in a controlled staging environment or during a maintenance window. Record which plugin or filter changes the result before re-enabling components one at a time.
Use the error and status code to choose the next check
| Observed symptom | Most useful first check | What confirms the diagnosis |
|---|---|---|
| “The uploaded file could not be moved” | Destination path, parent traversal, owner, and PHP write access | Logs show a failed rename or move_uploaded_file at the site-specific path. |
| “Unable to create directory” | Missing directory, parent ownership, ACLs, and disk space | The PHP account cannot create a test directory in the affected location. |
| HTTP 403 during upload | Apache/Nginx rules, Web Application Firewall, and security-policy logs | The server or policy log identifies the denied request or path. |
| “File type not permitted” | Network allowed types and uploader capability | A small file with an allowed MIME type succeeds for the same user. |
| Upload succeeds but media URL is 404 or 403 | Rewrite/location rules and legacy /files/ mapping |
The file exists on disk, but the web server maps its URL elsewhere or denies it. |
| Only large files fail | Network maximum, PHP size limits, proxy limits, and timeouts | A small permitted image succeeds while a file above one limit fails. |
Retest and verify the complete path
After each targeted change, repeat the same controlled test rather than uploading an arbitrary large file. Use a small JPEG or PNG that the network permits, upload it from the affected subsite, confirm that WordPress creates the expected year/month directory, and open the generated media URL in a private browser window. Then test the main site to ensure that a rewrite or ownership change did not break another site.
Keep the timestamp, site ID, filename, HTTP status, and the exact server change in your change record. If the test still fails, provide those details and the relevant PHP-FPM, Apache/Nginx, WordPress, and security-policy log entries to the person administering the host. Avoid repeated recursive permission changes: they can obscure the original cause and widen the attack surface.
Prevent the problem on future sites and migrations
- Document the network type, WordPress version, PHP-FPM account, document root, and upload-storage convention.
- When creating a site, verify its numeric ID and confirm that its modern
uploads/sites/<id>directory is created with the expected owner and group. - Keep Network Admin’s maximum size and allowed MIME list aligned with PHP and proxy limits, and review them after server migrations.
- Test both subdirectory and subdomain URLs, including the media URL generated after an upload.
- Monitor disk space, inode usage, quotas, and PHP temporary-storage health.
- Back up the database and upload directories before changing legacy routing or moving media storage.
- Use least-privilege service accounts and review ACL, SELinux, or AppArmor changes as part of deployment.
When to involve your host or server administrator
Escalate when you cannot identify the PHP account, do not control Apache/Nginx, share storage across nodes, or see denials in SELinux, AppArmor, a Web Application Firewall, or a hosting quota system. The administrator will need the affected site ID, exact path, timestamp, HTTP status, filename, and log excerpt. A managed WordPress or server-administration team is appropriate when the fix crosses filesystem ownership, PHP execution context, and web-server configuration; changing only the WordPress dashboard settings cannot repair those layers.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




