payloadcms/payload · error · FileRetrievalError

Unable to determine mimetype for file: ${doc.filename}

Error message

Unable to determine mimetype for file: ${doc.filename}

What it means

On the local-storage branch, after getFileByPath succeeds, getFileFromDoc needs a mimetype from file.mimetype falling back to doc.mimeType. If neither is present it throws FileRetrievalError. The on-disk file was readable but carried no type information.

Source

Thrown at packages/plugin-import-export/src/utilities/getFileFromDoc.ts:48

  const disableLocalStorage = uploadConfig.disableLocalStorage ?? false
  const staticDir = uploadConfig.staticDir || collectionConfig.slug

  const serverURL = req.payload.config.serverURL
  const isLocalFile = (serverURL && doc.url?.startsWith(serverURL)) || doc.url?.startsWith('/')

  if (!disableLocalStorage && isLocalFile && doc.filename) {
    // Local storage enabled - read directly from disk (efficient, no HTTP roundtrip)
    const filePath = `${staticDir}/${doc.filename}`
    const file = await getFileByPath(filePath)

    if (!file) {
      throw new Error(`File not found at path: ${filePath}`)
    }

    const mimetype = file.mimetype || doc.mimeType

    if (!mimetype) {
      throw new FileRetrievalError(req.t, `Unable to determine mimetype for file: ${doc.filename}`)
    }

    return {
      data: file.data,
      mimetype,
    }
  }

  if (doc.filename && doc.url) {
    // Cloud storage or external - fetch via Payload's file endpoint
    // getExternalFile constructs full URL, includes cookies for auth, and
    // the request goes through Payload's handler chain (including storage adapter)

    // For relative URLs, construct a full URL using formatAdminURL which properly
    // handles serverURL, basePath, and other config. This is important in job contexts
    // where request headers may not be available for URL construction.
    // Use serverURL from config, falling back to req.origin for local/job requests.
    const fileUrl = doc.url.startsWith('http')

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Persist doc.mimeType on upload so the fallback resolves.
  2. Ensure uploaded files retain their original extension so detection works.
  3. Backfill mimeType for existing local files.
Defensive patterns

Strategy: validation

Validate before calling

const mimetype = file.mimetype || doc.mimeType
if (!mimetype) {
  // derive from extension as a last resort, or fail fast with a clear message
  throw new Error(`No mimetype for local file ${doc.filename}; set doc.mimeType`)
}

Type guard

const hasAnyMimetype = (file: { mimetype?: unknown }, doc: { mimeType?: unknown }): boolean =>
  typeof file.mimetype === 'string' || typeof doc.mimeType === 'string'

Prevention

When it happens

Trigger: The local file has no detectable mimetype and the doc lacks mimeType. getFileByPath's mimetype detection (usually extension-based) returned undefined.

Common situations: File written without an extension; extension not in the mimetype map; doc schema predates the mimeType field.

Related errors


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