payloadcms/payload · error · APIError

Invalid upload reference.

Error message

Invalid upload reference.

What it means

`getFileFromUploadInstructions` expects `file` to be an object carrying an `uploadReference` that is itself a non-null object. If `file` is falsy, not an object, lacks `uploadReference`, or `uploadReference` is not an object, it throws `APIError` HTTP 400 `Invalid upload reference.` This guards the branch that decides between a staged upload (`uploadId`) and an adapter handler call.

Source

Thrown at packages/payload/src/uploads/getFileFromUploadInstructions.ts:22

import { APIError } from '../errors/APIError.js'
import { getStagedFile } from './stagedUpload.js'

export const getFileFromUploadInstructions = async ({
  collectionSlug,
  file,
  req,
}: {
  collectionSlug: string
  file: UploadInstructions['file']
  req: PayloadRequest
}): Promise<NonNullable<PayloadRequest['file']>> => {
  if (
    !file ||
    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

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Pass the **entire** `file` object returned by `POST /upload-instructions` unchanged into the document request: `file: instructions.file` (which includes `uploadReference`).
  2. Update the client SDK to the Payload version that emits `uploadReference`.
  3. Log the exact `file` value sent to find the dropped/renamed key.
  4. If building instructions manually, include `uploadReference: { uploadId }` (staged) or the adapter-specific reference object.

Example fix

// before — client sent only the filename
await payload.create({
  collection: 'media',
  data: { file: { filename: 'a.png' } }, // missing uploadReference
})

// after — pass the full file object from the instructions response
const instructions = await getUploadInstructions({ collectionSlug: 'media', filename, filesize, mimeType, req })
await payload.create({
  collection: 'media',
  data: {},
  file: instructions.file, // { filename, mimeType, size, uploadReference }
})
Defensive patterns

Strategy: type-guard

Validate before calling

function hasValidUploadReference(file: unknown): boolean {
  return !!file && typeof file === 'object' &&
    !!(file as any).uploadReference &&
    typeof (file as any).uploadReference === 'object'
}

const file = instructions.file
if (!hasValidUploadReference(file)) {
  throw new Error('uploadReference missing on file payload')
}

Type guard

type UploadFile = { filename: string; mimeType: string; size: number; uploadReference: Record<string, unknown> }
function isUploadFile(file: unknown): file is UploadFile {
  return !!file && typeof file === 'object' &&
    typeof (file as any).filename === 'string' &&
    typeof (file as any).mimeType === 'string' &&
    !!file && typeof (file as any).uploadReference === 'object' && (file as any).uploadReference !== null
}

Try / catch

try {
  await payload.create({ collection: 'media', data, file })
} catch (err) {
  if (err instanceof Error && /invalid upload reference/i.test(err.message)) {
    // re-request instructions and pass the full instructions.file object
  } else throw err
}

Prevention

When it happens

Trigger: A document create/update where the `file` payload (the `UploadInstructions['file']` shape returned by `/upload-instructions`) is missing, not an object, or its `uploadReference` is absent/not an object. Typically the client dropped or reshaped the `file` block returned by the instructions endpoint.

Common situations: The client stored only `filename`/`mimeType` and omitted `uploadReference`. A version mismatch: the client speaks an older upload protocol without `uploadReference`. A serialization step (JSON round-trip) dropped the key. The frontend sent `file: uploadInstructions.file.uploadReference` (one level too deep).

Related errors


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