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 _fileBuffer

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Add the file's mimetype (or a wildcard like 'image/*') to the collection's upload.mimeTypes array in the config.
  2. Rename the file so its extension is not in RESTRICTED_FILE_EXT_AND_TYPES, or confirm the client sends the correct Content-Type.
  3. If you intentionally accept restricted types, set upload.allowRestrictedFileTypes: true on the collection (disables the blocklist check entirely).
  4. 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

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


AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12). Data as JSON: /api/errors/769fdeaacd20ad14. Report an issue: GitHub.