payloadcms/payload · error · APIError
Uploaded file size does not match the expected size.
Error message
Uploaded file size does not match the expected size.
What it means
Thrown after the PUT body stream for a staged upload finishes: the total bytes received do not equal the `filesize` declared when the staged upload instructions were generated. Payload uses the declared size to pre-validate and atomically rename the temp file, so a mismatch means the upload cannot be finalized.
Source
Thrown at packages/payload/src/uploads/stagedUpload.ts:103
if (done) {
break
}
uploadedSize += value.byteLength
if (uploadedSize > upload.filesize) {
throw new APIError('Uploaded file is larger than expected.', 400)
}
let offset = 0
while (offset < value.byteLength) {
const { bytesWritten } = await file.write(value, offset)
offset += bytesWritten
}
}
if (uploadedSize !== upload.filesize) {
throw new APIError('Uploaded file size does not match the expected size.', 400)
}
} finally {
await file.close()
}
const collection = req.payload.collections[upload.collectionSlug]!.config
await checkFileRestrictions({
collection,
file: {
name: upload.filename,
data: Buffer.alloc(0),
mimetype: upload.mimeType,
size: upload.filesize,
tempFilePath: temporaryPath,
},
req,
})
View on GitHub (pinned to 00c58b35c0)
Solutions
- Verify the `filesize` value passed to `generateStagedUploadInstructions` matches the actual byte length of the blob you PUT.
- Ensure the HTTP client sends the entire body without early abort -- check for network interruptions or client-side timeouts.
- Confirm no intermediary (nginx client_max_body_size, CDN, or compression) alters the body length.
- If resuming, request fresh upload instructions for the correct file size rather than reusing an old uploadId.
Example fix
// before
const instructions = await generateStagedUploadInstructions({
filesize: file.size, // stale or wrong value
...
})
await fetch(instructions.request.url, { method: 'PUT', body: partialBlob })
// after
const buf = await file.arrayBuffer()
const instructions = await generateStagedUploadInstructions({
filesize: buf.byteLength, // exact byte count
...
})
await fetch(instructions.request.url, { method: 'PUT', body: buf }) Defensive patterns
Strategy: validation
Validate before calling
// Before PUT, confirm the blob byte length matches the declared size
const buf = await file.arrayBuffer()
if (buf.byteLength !== declaredFilesize) {
throw new Error(`Size mismatch: blob is ${buf.byteLength}, expected ${declaredFilesize}`)
}
await fetch(uploadUrl, { method: 'PUT', body: buf, headers: { 'Content-Length': String(buf.byteLength) } }) Try / catch
// Wrap the PUT; on failure, re-stage instead of retrying with stale uploadId
try {
await putStagedBytes(uploadId, buffer)
} catch (e) {
if (e instanceof APIError && e.message.includes('does not match')) {
const fresh = await generateStagedUploadInstructions({ filesize: buffer.byteLength, ... })
await putStagedBytes(fresh.uploadId, buffer)
} else throw e
} Prevention
- Always compute filesize from the exact buffer/arrayBuffer you will PUT, not from a File metadata field that may be stale.
- Set Content-Length explicitly on the PUT request.
- Treat upload instructions as single-use; regenerate on any failure.
When it happens
Trigger: A client sends a PUT to the `/upload-instructions/:uploadId` URL with a body whose total byte count is less than (or, having passed the larger-than check, somehow not equal to) the `filesize` encoded in the signed uploadId JWT. Typical causes: the client aborted early, a proxy truncated the body, or `Content-Length` / stream length disagrees with the value passed to `generateStagedUploadInstructions`.
Common situations: Client-side progress upload that stops sending chunks before completion; a reverse proxy or CDN that buffers or strips part of the body; the `filesize` passed at instruction-generation time was computed incorrectly (e.g. using a `File` object whose size changed, or a stat read before the file finished writing).
Related errors
- Upload collection ${upload.collectionSlug} was not found
- Uploaded file is larger than expected.
- Invalid staged upload.
- Field ${field.label} has invalid relationship '${relationshi
- File type '${file.mimetype}' is not allowed.
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/528f3fddf40cc1a8.
Report an issue: GitHub.