payloadcms/payload · error · ValidationError
File type '${file.mimetype}' is not allowed.
Error message
File type '${file.mimetype}' is not allowed. What it means
Thrown by checkFileRestrictions on the fast-path that skips buffer inspection (checkFileContents === false), used by the upload-instructions endpoint and pre-flight checks. The uploaded file's mimetype fails validation: if the collection defines upload.mimeTypes, the file's mimetype must match one of them (via validateMimeType prefix matching, where '*' is stripped); otherwise the file is rejected when its mimetype OR filename extension matches the RESTRICTED_FILE_EXT_AND_TYPES blocklist (executables, scripts, HTML, etc.).
Source
Thrown at packages/payload/src/uploads/checkFileRestrictions.ts:101
)
}
// Skip validation if `allowRestrictedFileTypes` is true
if (allowRestrictedFileTypes) {
return
}
if (!checkFileContents) {
const isAllowed = configMimeTypes.length
? validateMimeType(file.mimetype, configMimeTypes)
: !RESTRICTED_FILE_EXT_AND_TYPES.some(
({ extensions, mimeType }) =>
mimeType === file.mimetype ||
extensions.some((extension) => file.name.toLowerCase().endsWith(extension)),
)
if (!isAllowed) {
throw new ValidationError({
errors: [{ message: `File type '${file.mimetype}' is not allowed.`, path: 'file' }],
})
}
return
}
// For temp files, use fileTypeFromFile so large files (e.g. video) are never loaded into memory
// just for detection. For content validation (SVG safety, PDF integrity), the full buffer is
// loaded lazily and only when the file type actually requires it.
const { tempFilePath } = file
const isTempFile = !!tempFilePath && (!file.data || file.data.length === 0)
// Lazily reads the full file — only reached for small text-based types (SVG, PDF).
let _fileBuffer: Buffer | undefined
const getFileBuffer = async (): Promise<Buffer> => {
if (_fileBuffer) {
return _fileBufferView on GitHub (pinned to 00c58b35c0)
Solutions
- Add the file's mimetype (or a wildcard like 'image/*') to the collection's upload.mimeTypes array in the config.
- Rename the file so its extension is not in RESTRICTED_FILE_EXT_AND_TYPES, or confirm the client sends the correct Content-Type.
- If you intentionally accept restricted types, set upload.allowRestrictedFileTypes: true on the collection (disables the blocklist check entirely).
- Verify the client is sending the real mimetype (FormData/Blob type) rather than a default 'application/octet-stream'.
Example fix
// before
upload: { staticDir: 'media', mimeTypes: ['application/pdf'] }
// after — allow all images plus PDFs and SVGs
upload: { staticDir: 'media', mimeTypes: ['image/*', 'application/pdf', 'image/svg+xml'] } Defensive patterns
Strategy: validation
Validate before calling
import { validateMimeType } from 'payload/utilities' // or replicate the prefix logic
const ALLOWED = ['image/*', 'application/pdf', 'image/svg+xml'] // mirror upload.mimeTypes
function isAllowedRequest(mimetype: string, filename: string): boolean {
const cleaned = ALLOWED.map((m) => m.replace('*', ''))
const matchesConfig = cleaned.some((c) => mimetype.startsWith(c))
return matchesConfig
}
// call before upload:
if (!isAllowedRequest(file.type, file.name)) throw new Error('Pick a file of an allowed type') Type guard
const isAcceptableMime = (m: string): boolean =>
['image/', 'video/', 'audio/', 'application/pdf', 'image/svg+xml'].some((p) =>
m.startsWith(p.replace('*', '')),
) Try / catch
try {
await payload.create({ collection: 'media', data, file })
} catch (e) {
if (e instanceof APIError && /File type .* is not allowed/.test(e.message)) {
notifyUser('That file type is not allowed. Allowed: ' + ALLOWED.join(', '))
} else throw e
} Prevention
- Keep the client's accepted attribute in sync with upload.mimeTypes (e.g. <input accept='image/*,application/pdf'>).
- Document the configured mimeTypes in your API docs so consumers know the contract.
- Use wildcard entries ('image/*') carefully — they broaden acceptance.
- Run a pre-flight check against the upload-instructions endpoint to fail fast.
When it happens
Trigger: POST /api/:collection/upload-instructions or a local upload where (a) upload.mimeTypes is set and file.mimetype does not start with any configured entry (note '*' is stripped, so 'image/*' matches any 'image/...'), or (b) upload.mimeTypes is unset and the file extension/mimetype is in the built-in restricted list (e.g. .exe, .html, .php, .js, .bat).
Common situations: Forgetting to add 'application/pdf' or a specific image type to upload.mimeTypes; uploading an SVG with mimetype 'image/svg+xml' while only listing generic types; client sending a generic 'application/octet-stream' that isn't in the allow list; trying to upload HTML/JS that the blocklist catches even when no mimeTypes are configured.
Related errors
- Field ${field.label} has invalid relationship '${relationshi
- File type ${mimeTypeFromExtension} (from extension ${typeFro
- Upload collection ${upload.collectionSlug} was not found
- Invalid upload collection.
- Invalid template given
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/769fdeaacd20ad14.
Report an issue: GitHub.