payloadcms/payload · error · FileRetrievalError
There was a problem while uploading the file. ${message}
Error message
There was a problem while uploading the file. ${message} What it means
When duplicating or re-uploading, Payload tries to re-acquire the original file either locally (`getFileByPath`) or remotely (`getExternalFile`). Any error thrown inside that block — disk read failure, missing local file, DNS error, 4xx/5xx on the remote fetch, SSRF block — is wrapped and re-thrown as a `FileRetrievalError` (HTTP 500). The original error message is appended (`There was a problem while retrieving the file. <msg>`) so callers can see the root cause.
Source
Thrown at packages/payload/src/uploads/generateFileData.ts:146
try {
if (!disableLocalStorage && isLocalFile) {
// File is stored locally
const filePath = `${staticPath}/${filename}`
const response = await getFileByPath(filePath)
file = response
overwriteExistingFiles = true
} else if (filename && url) {
// File is remote
file = await getExternalFile({
data: incomingFileData as unknown as FileData,
req,
uploadConfig: collectionConfig.upload,
})
overwriteExistingFiles = true
}
} catch (err: unknown) {
throw new FileRetrievalError(req.t, err instanceof Error ? err.message : undefined)
}
}
if (isDuplicating) {
overwriteExistingFiles = false
}
if (!file) {
if (throwOnMissingFile) {
throw new MissingFile(req.t)
}
return {
data: incomingFileData!,
files: [],
}
}
View on GitHub (pinned to 00c58b35c0)
Solutions
- Check server logs for the appended root-cause message to identify local-vs-remote failure.
- For local failures: confirm the file exists at `${staticPath}/${filename}` and the process has read permission; restore from backup or re-upload.
- For remote failures: verify the `url` is reachable and the server can egress to it (no firewall/proxy block); refresh expired signed URLs.
- Run a storage-consistency sweep to find dangling references and either re-upload or delete the orphan documents.
- If migrating storage, backfill `staticDir`/`staticURL` so existing documents resolve correctly.
Example fix
// before — duplicate references a missing local file
await payload.create({ collection: 'media', data: { _duplicateFrom: id } })
// after — verify the source exists first, else re-upload
import fs from 'node:fs/promises'
try {
await fs.access(`${staticDir}/${doc.filename}`)
await payload.create({ collection: 'media', data: { _duplicateFrom: id } })
} catch {
// source gone — fetch bytes and create with req.file instead
} Defensive patterns
Strategy: try-catch
Validate before calling
import fs from 'node:fs/promises'
async function sourceReadable(staticDir: string, filename: string | null, url?: string | null) {
if (filename && (filename.includes('../') || filename.includes('..\\'))) return false
if (!filename) return false
try {
await fs.access(`${staticDir}/${filename}`)
return true
} catch {
return false
}
}
if (!(await sourceReadable(staticDir, doc.filename, doc.url))) {
// re-upload bytes instead of duplicating from a missing source
} Type guard
import { APIError } from 'payload'
function isFileRetrievalError(err: unknown): err is InstanceType<typeof APIError> {
return err instanceof Error && /problem while retrieving the file/i.test(err.message)
} Try / catch
try {
await payload.create({ collection: 'media', data: { _duplicateFrom: id } })
} catch (err) {
if (isFileRetrievalError(err)) {
// log the appended root cause, then re-upload the bytes directly
} else throw err
} Prevention
- Before duplicating, confirm the source file exists at `${staticDir}/${filename}`.
- Keep storage paths stable across deploys; migrate `staticDir` with the data.
- Run periodic consistency checks between DB records and the storage volume.
When it happens
Trigger: A duplicate/update with `isDuplicating` or `shouldReupload` true, where: (a) local storage is enabled and `getFileByPath(`${staticPath}/${filename}`)` fails (ENOENT, permission denied), or (b) the file is remote and `getExternalFile` throws (network, redirect limit, SSRF, non-ok status). The surrounding `catch (err)` converts any such error into `FileRetrievalError`.
Common situations: The media directory was moved/rotated between deploys and the stored path no longer exists. Local storage was disabled (`disableLocalStorage`) but the document still references a local URL. The remote URL expired (signed S3 link, CDN purge). A storage migration left dangling references. Filesystem permissions changed.
Related errors
- You are not allowed to perform this action.
- storage contains an invalid entry: expected an object with a
- Field ${field.label} has reserved name '${fieldName}'.
- Field "${field.name}" of type "${field.type}" has an empty r
- Field ${field.label} has invalid relationship '${relationshi
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/90762598b942505f.
Report an issue: GitHub.