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

  1. Install and register the storage adapter plugin for the collection in `payload.config.ts` (e.g. `s3Storage({ collections: { media: { ... } } })`).
  2. Verify the adapter version registers `upload.handlers` on the collection config.
  3. If using local storage, make the client use the staged path (request instructions that return `{ uploadReference: { uploadId } }`).
  4. 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

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


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