{"record":{"id":"fe39beecd408cfd1","repo":"payloadcms/payload","slug":"exceeded-file-size-limit-limit-bytestomb-files","errorCode":null,"errorMessage":"Exceeded file size limit. Limit: ${bytesToMB(filesizeLimit).toFixed(2)}MB, got: ${bytesToMB(upload.filesize).toFixed(2)}MB","messagePattern":"Exceeded file size limit\\. Limit: (.+?)MB, got: (.+?)MB","errorType":"http","errorClass":"APIError","httpStatus":400,"severity":"warning","filePath":"packages/payload/src/uploads/endpoints/uploadInstructions.ts","lineNumber":50,"sourceCode":"\nexport const getUploadInstructions = async ({\n  overrideAccess = false,\n  req,\n  ...upload\n}: {\n  overrideAccess?: boolean\n  req: PayloadRequest\n} & UploadInstructionsRequest): Promise<UploadInstructions> => {\n  const collection = req.payload.collections[upload.collectionSlug]\n  const uploadInstructions = collection?.config?.upload?.uploadInstructions\n\n  if (!collection?.config?.upload) {\n    throw new APIError(`Upload collection ${upload.collectionSlug} was not found`, 400)\n  }\n\n  const filesizeLimit = req.payload.config.upload.limits?.fileSize\n  if (filesizeLimit && upload.filesize > filesizeLimit) {\n    throw new APIError(\n      `Exceeded file size limit. Limit: ${bytesToMB(filesizeLimit).toFixed(2)}MB, got: ${bytesToMB(upload.filesize).toFixed(2)}MB`,\n      400,\n    )\n  }\n\n  await checkFileRestrictions({\n    checkFileContents: false,\n    collection: collection.config,\n    file: {\n      name: upload.filename,\n      data: Buffer.alloc(0),\n      mimetype: upload.mimeType,\n      size: upload.filesize,\n    },\n    req,\n  })\n\n  if (!uploadInstructions && !overrideAccess) {","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/payload/src/uploads/endpoints/uploadInstructions.ts#L32-L68","documentation":"Payload enforces a single, global upload file-size ceiling configured at `config.upload.limits.fileSize` (bytes). When a client asks for upload instructions with a declared `filesize` that exceeds this global limit, the `getUploadInstructions` helper rejects the request with HTTP 400 *before* any bytes are staged. This is distinct from per-collection MIME/extension checks (handled later by `checkFileRestrictions`) and from adapter-specific limits.","triggerScenarios":"Calling `POST /api/upload-instructions` (the `uploadInstructionsEndpoint`) — or the internal `getUploadInstructions({ collectionSlug, filename, filesize, mimeType, req })` — with a body whose `filesize` (a non-negative safe integer, validated by `isUploadInstructionsRequest`) is greater than `req.payload.config.upload.limits?.fileSize`. The global limit is read from the sanitized server config, not from the collection.","commonSituations":"A team sets a conservative `upload.limits.fileSize` (e.g. 10MB) and a user uploads a large video/PDF. The limit was lowered between releases and existing clients still send large files. The client reports the uncompressed size while intending to upload a compressed payload, so the declared `filesize` overshoots the cap even though the real bytes are smaller.","solutions":["Raise the global limit in `payload.config.ts`: `upload: { limits: { fileSize: <larger bytes> } }` and redeploy.","Compress/resize the file on the client before requesting upload instructions, and send the post-compression byte count as `filesize`.","Verify the client is sending the true final byte length (not a pre-transcode or padded size) and that the value is a non-negative safe integer.","If the per-collection cap should differ, move the restriction to `upload.mimeTypes`/custom hooks instead of relying solely on the global limit."],"exampleFix":"// before\nexport default buildConfig({\n  upload: { limits: { fileSize: 10_000_000 } }, // 10 MB\n})\n\n// after\nexport default buildConfig({\n  upload: { limits: { fileSize: 100_000_000 } }, // 100 MB\n})","handlingStrategy":"validation","validationCode":"import type { UploadInstructionsRequest } from 'payload'\n\nconst GLOBAL_FILE_SIZE_LIMIT = 50_000_000 // must match payload.config upload.limits.fileSize\n\nfunction assertWithinGlobalLimit(req: UploadInstructionsRequest) {\n  if (req.filesize > GLOBAL_FILE_SIZE_LIMIT) {\n    throw new Error(\n      `filesize ${req.filesize} exceeds global limit ${GLOBAL_FILE_SIZE_LIMIT}`,\n    )\n  }\n}\n\n// call before POST /upload-instructions\nassertWithinGlobalLimit({ collectionSlug: 'media', filename, filesize, mimeType })","typeGuard":"function isUploadInstructionsRequest(u: unknown): u is UploadInstructionsRequest {\n  return (\n    !!u && typeof u === 'object' &&\n    typeof (u as any).collectionSlug === 'string' &&\n    typeof (u as any).filename === 'string' &&\n    typeof (u as any).mimeType === 'string' &&\n    typeof (u as any).filesize === 'number' &&\n    Number.isSafeInteger((u as any).filesize) &&\n    (u as any).filesize >= 0 &&\n    (u as any).filesize <= GLOBAL_FILE_SIZE_LIMIT\n  )\n}","tryCatchPattern":"try {\n  const res = await fetch(`${url}/api/upload-instructions`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) })\n  if (res.status === 400) {\n    const body = await res.json().catch(() => ({}))\n    if (/file size limit/i.test(body.message ?? '')) {\n      // filesize too large — compress/resize and retry, or raise config limit\n    }\n  }\n} catch (err) {\n  // network error\n}","preventionTips":["Mirror the server's `config.upload.limits.fileSize` into a shared constant the client imports.","Compute filesize from the real bytes you will upload, never from a larger source artifact.","Compress media client-side before requesting upload instructions."],"tags":["upload","file-size","validation","configuration"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}