Fixing the File Type Not Permitted Upload Error
Current WordPress prints "Sorry, you are not allowed to upload this file type"; the older wording still fills tutorials and old installs. Both come from the same check, and the fix depends on whether the type is disallowed or the file is not what its extension says.
WordPress refused the upload because the file's type is not on the allowed list — and on a current site the message says so in different words. "Sorry, this file type is not permitted for security reasons." is the WordPress 5.x wording; since 6.0 the same refusal reads "Sorry, you are not allowed to upload this file type." Both are printed by the upload handler after wp_check_filetype_and_ext() has worked out what the file really is. Before changing anything, find out which of two situations you are in: a type WordPress does not accept, or a file whose contents do not match a type it does.
What the check does with a mislabelled file
For images, WordPress inspects the file's contents and trusts them over the extension. A PNG renamed to .jpg is detected as a PNG, and because PNG is an allowed type, it is accepted and renamed to .png on the way in. The same happens for a WebP saved with a .png extension. Mislabelled images are not the cause of this error; they upload with a corrected name.
The error appears when the real type is one WordPress does not allow for your user:
| What the file really is | Extension on it | Result |
|---|---|---|
| PNG, JPEG, GIF, WebP | Any image extension | Accepted, renamed to match |
| SVG | .png, .jpg, .svg |
Rejected — SVG is never allowed by default |
| HTML or JavaScript | Anything | Rejected unless the user has unfiltered_html |
| HEIC from a phone | .jpg, .heic |
Version-dependent; older releases cannot identify it and reject it |
PDF renamed to .docx |
.docx |
Rejected — contents and extension disagree on a non-image type |
| Executable, Flash | Anything | Rejected for everyone |
So the first question is what the file actually is. On a command line, file photo.jpg prints the detected type. On a desktop, the file's properties show it. If the real type is in the allowed set, the problem is elsewhere; if it is not, decide whether it should be.
Allowing a type that is not on the list
The allowed list is filterable through upload_mimes, covered in depth in upload_mimes. The shape for a safe addition:
add_filter( 'upload_mimes', 'ti_allow_csv' );
function ti_allow_csv( $mimes ) {
$mimes['csv'] = 'text/csv';
return $mimes;
}
The value is the MIME type WordPress will store for the attachment. For CSV, PHP's content detection usually reports text/plain, and WordPress already treats that as compatible with text/csv, so the single filter is enough. For a type where detection and declaration disagree in a way core does not reconcile, the upload still fails after the filter, and the wp_check_filetype_and_ext filter is where the two are matched up — a sign the type is one WordPress treats with suspicion for a reason.
SVG is the special case
SVG is the most requested type and the one WordPress will not allow by default, because an SVG is XML and can carry scripts that run when the image is viewed. Allowing it through upload_mimes alone makes the error go away and makes every uploader a potential source of stored scripts. A plugin that sanitises SVG on upload, restricted to administrators, is the acceptable form of allowing it. A stored script in uploads is one of the entry points behind a hacked site, and the honest trade-off is that logos usually survive conversion to PNG at the sizes a site uses.
HTML, JavaScript and the capability
.htm, .html and .js are in the allowed list only for users who hold unfiltered_html. On a single site that is administrators and editors; on multisite only super admins. That is why the same file uploads for one account and fails for another. If editors genuinely need to upload HTML — a downloadable template, say — zip it; a .zip is allowed for every uploader and sidesteps the question of executing it.
Multisite
On a network, the allowed extensions are also a list in Network Admin › Settings › Upload Settings, and that list wins. A type allowed by a filter on one site is still rejected until it appears in the network list, which is why the same snippet works on a single site and not on a network.
The constant that should stay off
define( 'ALLOW_UNFILTERED_UPLOADS', true ) disables the type and content checks for users with unfiltered_upload. It is the quickest way to make the error disappear and the quickest way to let a compromised editor account place a web shell in wp-content/uploads. If it is set on a site you inherited, remove it and allow the specific types the site needs. The uploads folder is served directly by the web server, and a file placed there is reachable by URL without WordPress in between.
Verify
- Upload a correctly exported file of an allowed type: it succeeds and shows in the media library.
- Rename a PNG to
.jpgand upload it: it succeeds and the stored file ends in.png— confirming the content check corrects rather than rejects images. - After adding a type through the filter, upload a genuine file of that type as an editor: it succeeds for the roles you intended and not for others, if you gated it.
- On a network, confirm the extension is in the network list as well.
Frequently asked
- Because that is the current wording. WordPress 5.x printed 'Sorry, this file type is not permitted for security reasons'; every supported 6.x release prints 'Sorry, you are not allowed to upload this file type.' Same check, same causes, same fixes.
- No. It disables the type check for everyone who can upload, which lets any contributor store an executable or an HTML file with scripts in your uploads folder. Allow the single type you need through the upload_mimes filter instead.
- HTML and JavaScript files are allowed only for users with the unfiltered_html capability, which administrators hold on a single site. Many SVG and font plugins also gate their allowance by role. If the file is safe for editors to upload, the role condition is what to change.