{"record":{"id":"20bd31e3c5694a85","repo":"payloadcms/payload","slug":"you-are-not-allowed-to-perform-this-action-20bd31","errorCode":null,"errorMessage":"You are not allowed to perform this action.","messagePattern":"You are not allowed to perform this action\\.","errorType":"exception","errorClass":"Forbidden","httpStatus":403,"severity":"error","filePath":"packages/payload/src/uploads/stagedUpload.ts","lineNumber":168,"sourceCode":"  collectionSlug: string\n  req: PayloadRequest\n  uploadReference: unknown\n}): Promise<File> => {\n  if (\n    !uploadReference ||\n    typeof uploadReference !== 'object' ||\n    Array.isArray(uploadReference) ||\n    !('uploadId' in uploadReference) ||\n    typeof uploadReference.uploadId !== 'string'\n  ) {\n    throw new APIError('Invalid staged upload.', 400)\n  }\n\n  const { uploadId } = uploadReference\n  const upload = await verifyUploadID(req, uploadId)\n\n  if (upload.collectionSlug !== collectionSlug || upload.user !== getUser(req)) {\n    throw new Forbidden(req.t)\n  }\n\n  const directory = await getUploadDirectory(req, upload.collectionSlug)\n  const tempFilePath = path.join(directory, upload.id)\n  let data: Buffer\n\n  try {\n    data = await fs.readFile(tempFilePath)\n  } catch {\n    throw new APIError('Staged upload was not found.', 400)\n  }\n\n  if (data.length !== upload.filesize) {\n    await fs.rm(tempFilePath, { force: true })\n    throw new APIError('Staged upload is incomplete.', 400)\n  }\n\n  await fs.rm(tempFilePath, { force: true })","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/payload/src/uploads/stagedUpload.ts#L150-L186","documentation":"Thrown as a `Forbidden` error when a document create/update tries to consume a staged upload that belongs to a different collection or a different user than the one making the request. The staged upload JWT embeds `collectionSlug` and `user`; both must match the current request.","triggerScenarios":"The `uploadId` was generated for collection A but the create/update targets collection B; or the `uploadId` was generated by user X but user Y (or an anonymous request) submits the document that references it.","commonSituations":"Sharing an uploadId across users in a multi-tenant app; generating instructions for one collection but POSTing to another; a session changed (logout / re-login as different user) between staging and consuming the upload; the `getUser` key (`collection:id`) differs because the auth strategy changed.","solutions":["Ensure the same authenticated session that called `generateStagedUploadInstructions` also submits the create/update request.","Confirm the collection slug in the upload instructions matches the collection slug of the target document operation.","Do not reuse uploadIds across users -- each user must stage their own upload.","If impersonation or admin-on-behalf-of flows are needed, generate the instructions in the target user's context."],"exampleFix":"// before -- instructions generated as user A, consumed as user B\nconst instr = await adminClient.generateInstructions({ collectionSlug: 'media', ... })\nawait userBClient.create({ collection: 'media', data: { file: { uploadReference: { uploadId: instr.file.uploadReference.uploadId } } } })\n\n// after -- same session for both steps\nconst instr = await userClient.generateInstructions({ collectionSlug: 'media', ... })\nawait userClient.create({ collection: 'media', data: { file: { uploadReference: { uploadId: instr.file.uploadReference.uploadId } } } })","handlingStrategy":"validation","validationCode":"// Ensure the same user session and collection are used for staging and consuming\nconst userKey = `${req.user.collection}:${req.user.id}`\n// The uploadId JWT embeds user and collectionSlug -- regenerate if either changes\nif (sessionChanged) {\n  const fresh = await generateStagedUploadInstructions({ collectionSlug, req, ... })\n}","typeGuard":null,"tryCatchPattern":"try {\n  await payload.create({ collection, data })\n} catch (e) {\n  if (e.name === 'Forbidden') {\n    // re-authenticate or re-stage in the correct user context\n  } else throw e\n}","preventionTips":["Keep the authentication token identical between staging and consuming.","Do not share uploadIds across users or collections.","If user context changes mid-flow, re-stage the upload."],"tags":["upload","staged-upload","authorization","forbidden"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}