payloadcms/payload · error · ValidationError

Could not read uploaded file for validation.

Error message

Could not read uploaded file for validation.

What it means

Thrown when the lazy getFileBuffer() helper cannot read the temp file from disk via fs.readFile during content-level validation (SVG safety, PDF integrity). This path is only reached for temp-file uploads (large files written to disk by the multipart parser) whose buffer is empty, and only when the file's detected/extension type requires reading contents.

Source

Thrown at packages/payload/src/uploads/checkFileRestrictions.ts:128

  // 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
    }
    if (!isTempFile || !tempFilePath) {
      return (_fileBuffer = file.data)
    }
    try {
      _fileBuffer = await fs.readFile(tempFilePath)
      return _fileBuffer
    } catch {
      throw new ValidationError({
        errors: [{ message: 'Could not read uploaded file for validation.', path: 'file' }],
      })
    }
  }

  // Secondary mimetype check to assess file type from buffer
  if (configMimeTypes.length > 0) {
    let detected
    try {
      detected =
        isTempFile && tempFilePath
          ? await fileTypeFromFile(tempFilePath)
          : await fileTypeFromBuffer(file.data)
    } catch {
      throw new ValidationError({
        errors: [{ message: 'Could not read uploaded file for type detection.', path: 'file' }],
      })
    }

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Ensure the OS temp directory is not garbage-collected during the request lifecycle (raise TMPFILES age / disable cron cleanup of the upload temp dir).
  2. Confirm tempFilePath on the file object resolves to an existing, readable file before checkFileRestrictions runs.
  3. If using a custom storage adapter, verify it writes temp files to a stable, process-accessible location.
  4. Handle the ValidationError in the upload route and surface a retry prompt to the user.

Example fix

// before — temp file may vanish before validation
await checkFileRestrictions({ checkFileContents: true, collection, file, req })
// after — guard reads and retry on transient FS errors
import { existsSync } from 'fs'
if (file.tempFilePath && !existsSync(file.tempFilePath)) {
  throw new Error('Temp file vanished; please re-upload.')
}
await checkFileRestrictions({ checkFileContents: true, collection, file, req })
Defensive patterns

Strategy: try-catch

Validate before calling

import { existsSync, accessSync, constants } from 'fs'
function tempFileReadable(p?: string): boolean {
  if (!p) return true // in-memory upload, not applicable
  try { accessSync(p, constants.R_OK); return existsSync(p) } catch { return false }
}
// before upload pipeline:
if (file.tempFilePath && !tempFileReadable(file.tempFilePath)) throw new Error('Temp file unreadable')

Type guard

const hasReadableTempFile = (f: { tempFilePath?: string }): boolean =>
  !f.tempFilePath || (f.tempFilePath.length > 0)

Try / catch

try {
  await payload.create({ collection: 'media', file })
} catch (e) {
  if (e instanceof ValidationError && /Could not read uploaded file/.test(e.message)) {
    askUserToRetry('Temporary file could not be read. Please re-upload.')
  } else throw e
}

Prevention

When it happens

Trigger: A large uploaded file was written to a temp path, then that temp file was deleted, moved, or made unreadable (permissions, container volume unmount) between multipart parse and the content-validation step. Also reachable if tempFilePath points to a non-existent path due to a custom upload adapter or a tmp cleanup job.

Common situations: OS temp directory cleanup (systemd-tmpfiles, cron) running mid-request; Docker/k8s restarting and wiping the tmpfs; reverse proxy or middleware stripping the temp file; misconfigured upload.adapater setting an invalid tempFilePath; concurrent request or cleanup hook removing the temp file.

Related errors


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