payloadcms/payload · error · APIError
uploadConfig.handlers is not present for ${collectionSlug}
Error message
uploadConfig.handlers is not present for ${collectionSlug} What it means
When `file.uploadReference` has no `uploadId` (i.e. it is an adapter-managed reference, not a staged upload), Payload falls back to the collection's `upload.handlers`. If the collection's `config.upload` is missing or has no `handlers` array, it throws `APIError` (default HTTP 500) `uploadConfig.handlers is not present for <collectionSlug>`. This indicates a misconfigured adapter integration.
Source
Thrown at packages/payload/src/uploads/getFileFromUploadInstructions.ts:36
typeof file !== 'object' ||
!file.uploadReference ||
typeof file.uploadReference !== 'object'
) {
throw new APIError('Invalid upload reference.', 400)
}
/**
* Handlers fetch files uploaded to a storage provider. An uploadId points to a temporary file
* already stored by Payload, so no handler is needed.
*/
if ('uploadId' in file.uploadReference) {
return getStagedFile({ collectionSlug, req, uploadReference: file.uploadReference })
}
const uploadConfig = req.payload.collections[collectionSlug]!.config.upload
if (!uploadConfig || !uploadConfig.handlers) {
throw new APIError('uploadConfig.handlers is not present for ' + collectionSlug)
}
let response: null | Response = null
let error: unknown
for (const handler of uploadConfig.handlers) {
try {
const result = await handler(req, {
doc: null!,
params: {
collection: collectionSlug,
filename: file.filename,
uploadReference: file.uploadReference,
},
})
if (result) {
response = result
/**View on GitHub (pinned to 00c58b35c0)
Solutions
- Install and register the storage adapter plugin for the collection in `payload.config.ts` (e.g. `s3Storage({ collections: { media: { ... } } })`).
- Verify the adapter version registers `upload.handlers` on the collection config.
- If using local storage, make the client use the staged path (request instructions that return `{ uploadReference: { uploadId } }`).
- For custom adapters, ensure the plugin sets `collectionConfig.upload.handlers`.
Example fix
// before — collection has upload but no adapter plugin
export default buildConfig({
collections: [{ slug: 'media', upload: { staticURL: '/media', staticDir: 'media' } }],
})
// after — register an adapter that provides handlers
import { s3Storage } from '@payloadcms/storage-s3'
export default buildConfig({
collections: [{ slug: 'media', upload: { staticURL: '/media', staticDir: 'media' } }],
plugins: [
s3Storage({
collections: { media: true },
bucket: process.env.S3_BUCKET!,
config: { endpoint: process.env.S3_ENDPOINT },
}),
],
}) Defensive patterns
Strategy: validation
Validate before calling
function collectionHasHandlers(config: { upload?: { handlers?: unknown[] } }): boolean {
return Array.isArray(config.upload?.handlers) && (config.upload?.handlers?.length ?? 0) > 0
}
const col = payload.collections['media']?.config
if (!collectionHasHandlers(col)) {
throw new Error('Register a storage adapter that provides upload.handlers for media')
} Type guard
function hasHandlers(cfg: unknown): cfg is { upload: { handlers: Array<(req: any, args: any) => unknown> } } {
return !!cfg && typeof cfg === 'object' &&
!!(cfg as any).upload &&
Array.isArray((cfg as any).upload.handlers) &&
(cfg as any).upload.handlers.length > 0
} Try / catch
try {
await payload.create({ collection: 'media', data, file })
} catch (err) {
if (err instanceof Error && /uploadConfig\.handlers is not present/i.test(err.message)) {
// register the storage adapter plugin, or switch the client to staged uploads
} else throw err
} Prevention
- Register the storage adapter plugin in `payload.config.ts` for upload collections.
- For local storage, use staged uploads (request `{ uploadReference: { uploadId } }`).
- Pin adapter versions that are known to register `handlers`.
When it happens
Trigger: `getFileFromUploadInstructions` receives a `file.uploadReference` without `uploadId`, and `req.payload.collections[collectionSlug].config.upload` is either undefined or has no `handlers` property. The reference is therefore unresolvable: not a staged upload, and no adapter handler to call.
Common situations: A storage adapter (S3/GCS/Azure/R2/Vercel Blob) was supposed to register `upload.handlers` but wasn't installed or wired in `payload.config.ts` `plugins`. The adapter plugin is present but its version is too old to register handlers. A custom adapter forgot to set `handlers`. The collection is plain local-storage but the client sent an adapter-style reference.
Related errors
- Expected response from the upload handler.
- Exceeded file size limit. Limit: ${bytesToMB(filesizeLimit).
- Operator handler "${handler.name}" cannot define both "build
- Operator handlers "${handlerA.name}" and "${handlerB.name}"
- Compound indexes within localized and non localized fields a
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/68313919640ab86d.
Report an issue: GitHub.