payloadcms/payload · error · APIError
Staged upload not found. Complete the upload action first, o
Error message
Staged upload not found. Complete the upload action first, or use base64 for small local files.
What it means
The MCP file-input resolver throws this 400 when `source: 'uploadReference'` is used but `getFileFromUploadInstructions` cannot locate a staged upload matching the supplied `file.uploadReference`. It is a deliberate re-wrap of the internal 'Staged upload was not found.' error so the caller knows the two-step upload flow was not completed.
Source
Thrown at packages/plugin-mcp/src/mcp/builtin/collections/fileInput.ts:61
export async function resolveFile({
collectionSlug,
input,
req,
}: {
collectionSlug: CollectionSlug
input?: FileInput
req: PayloadRequest
}): Promise<File | undefined> {
if (!input) {
return undefined
}
if (input.source === 'uploadReference') {
try {
return await getFileFromUploadInstructions({ collectionSlug, file: input.file, req })
} catch (error) {
if (error instanceof Error && error.message === 'Staged upload was not found.') {
throw new APIError(
'Staged upload not found. Complete the upload action first, or use base64 for small local files.',
400,
)
}
throw error
}
}
const uploadConfig = req.payload.collections[collectionSlug]?.config.upload
if (!uploadConfig) {
throw new APIError(`Collection "${collectionSlug}" does not support file uploads.`, 400)
}
const maxFileSize = req.payload.config.upload.limits?.fileSize
let file: File
if (input.source === 'base64') {View on GitHub (pinned to 00c58b35c0)
Solutions
- Complete the dispatch upload (PUT the bytes to the signed URL returned by `generateUploadInstructions`) before calling the MCP tool with that `uploadReference`
- For small local files, switch to `source: 'base64'` which is single-step
- Regenerate upload instructions if the signed URL has expired and obtain a fresh `uploadReference`
- Verify the `uploadReference.prefix` matches the collection the tool is operating on
Example fix
// before — uploadReference supplied before the dispatch PUT
{ source: 'uploadReference', file: { filename, mimeType, size, uploadReference: { prefix } } }
// after — small file via base64, single step
{ source: 'base64', name: 'logo.png', mimeType: 'image/png', data: base64String } Defensive patterns
Strategy: validation
Validate before calling
// Verify the dispatch PUT succeeded before passing an uploadReference
async function ensureDispatched(signedUrl: string, bytes: Buffer) {
const res = await fetch(signedUrl, { method: 'PUT', body: bytes })
if (!res.ok) throw new Error(`dispatch upload failed: ${res.status}`)
} Try / catch
import { APIError } from 'payload'
try {
await tool.call({ source: 'uploadReference', file })
} catch (e) {
if (e instanceof APIError && e.statusCode === 400 && /Staged upload not found/.test(e.message)) {
// fall back to base64 for small files
return tool.call({ source: 'base64', name: file.filename, mimeType: file.mimeType, data: bytes.toString('base64') })
}
throw e
} Prevention
- Always run the dispatch PUT and confirm a 2xx before referencing the staged upload
- Treat uploadReference as single-use — do not replay it
- Default to base64 for files under a few hundred KB to avoid the two-step flow
- Regenerate upload instructions if more than ~3 hours pass (Azure SAS window)
When it happens
Trigger: Calling an MCP upload tool with `source: 'uploadReference'` before the dispatch PUT to the signed URL has finished; passing an `uploadReference` whose staged prefix was already consumed or whose SAS token expired; passing an uploadReference produced for collection A to a tool operating on collection B.
Common situations: Forgetting the dispatch step after `generateUploadInstructions`; calling the create/update MCP tool twice with the same reference (second call finds nothing); Azure SAS token older than 3 hours; cross-collection upload-reference reuse.
Related errors
- File data must be valid base64.
- No file data provided for import
- MCP overrideAccess must be "true" or "false".
- Collection "${collectionSlug}" does not support file uploads
- Uploading files from URLs is disabled for collection "${coll
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/b3b6f815fae1ecfe.
Report an issue: GitHub.