payloadcms/payload · error · APIError
Expected response from the upload handler.
Error message
Expected response from the upload handler.
What it means
When resolving an adapter-style upload reference, Payload iterates `uploadConfig.handlers`; each handler may return a `Response` (success → loop breaks) or `null` (try next). If **all** handlers return null/falsy (or threw and were swallowed into the `error` variable), the function logs the last handler error (if any) and throws `APIError` (default HTTP 500) `Expected response from the upload handler.`
Source
Thrown at packages/payload/src/uploads/getFileFromUploadInstructions.ts:72
/**
* - If a handler returns a Response, the response will be sent to the client and no further handlers will be run.
* - If a handler returns null, the next handler will be run.
*
* @see packages/payload/src/uploads/types.ts
*/
break
}
} catch (err) {
error = err
}
}
if (!response) {
if (error) {
req.payload.logger.error(error)
}
throw new APIError('Expected response from the upload handler.')
}
if (response.status >= 300 && response.status < 400) {
const redirectUrl = response.headers.get('Location')
if (redirectUrl) {
response = await fetch(redirectUrl)
}
}
return {
name: file.filename,
data: Buffer.from(await response.arrayBuffer()),
mimetype: response.headers.get('Content-Type') || file.mimeType,
size: file.size,
uploadReference: file.uploadReference,
}
}
View on GitHub (pinned to 00c58b35c0)
Solutions
- Check the Payload server logs for the captured handler `error` — it carries the real cause.
- Verify the storage adapter credentials/region/bucket match the upload reference.
- Ensure the adapter's handler returns a `Response` for valid references and throws (not returns null) for genuine errors so they surface.
- Confirm the `uploadReference` produced by `/upload-instructions` matches what the handler expects (key, prefix, region).
- Update the adapter plugin — older handlers were more likely to swallow errors.
Example fix
// before — custom handler swallows errors and returns null
handlers: [async (req, args) => {
try { return await fetchFromMyStore(args.params.uploadReference) }
catch { return null }
}]
// after — let errors propagate so they are logged and surfaced
handlers: [async (req, args) => {
return await fetchFromMyStore(args.params.uploadReference) // throws on failure
}] Defensive patterns
Strategy: try-catch
Validate before calling
async function handlerReturnsResponse(handler: (req: any, args: any) => unknown, args: any): Promise<boolean> {
try {
const r = await handler({} as any, args)
return r instanceof Response
} catch {
return false
}
}
const handlers = collection.upload?.handlers ?? []
if (!handlers.some((h) => typeof h === 'function')) {
throw new Error('No upload handler will produce a Response')
} Type guard
import { APIError } from 'payload'
function isExpectedResponseError(err: unknown): err is InstanceType<typeof APIError> {
return err instanceof Error && /expected response from the upload handler/i.test(err.message)
} Try / catch
try {
await payload.create({ collection: 'media', data, file })
} catch (err) {
if (isExpectedResponseError(err)) {
// check payload.logger output for the captured handler error
// verify adapter credentials/region/bucket and that the reference is valid
} else throw err
} Prevention
- Ensure adapter handlers return a `Response` for valid references and throw on error (not return null).
- Verify storage credentials, region, and bucket match the upload reference.
- Keep the adapter plugin up to date.
When it happens
Trigger: `getFileFromUploadInstructions` with an adapter reference where every handler in `uploadConfig.handlers` returns `null`/void/undefined, or each throws an exception caught by the per-handler `try/catch`. The last captured error is logged, but the surfaced message is generic.
Common situations: A storage adapter handler cannot locate the object (key mismatch, deleted blob) and returns null instead of throwing. The adapter credentials are wrong and the handler silently fails. A custom handler has a bug causing it to resolve undefined. The upload reference points to an object the handler cannot fetch (wrong bucket, region).
Related errors
- uploadConfig.handlers is not present for ${collectionSlug}
- There was a problem while uploading the file.
- 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
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/368ff6a64d2f6fd7.
Report an issue: GitHub.