{"record":{"id":"3a302f7972c4f732","repo":"payloadcms/payload","slug":"collection-collectionslug-was-not-found-in-r2-s","errorCode":null,"errorMessage":"Collection ${collectionSlug} was not found in R2 Storage options","messagePattern":"Collection (.+?) was not found in R2 Storage options","errorType":"http","errorClass":"APIError","httpStatus":500,"severity":"error","filePath":"packages/storage-r2/src/handleMultiPartUpload.ts","lineNumber":46,"sourceCode":"    : Boolean(req.user)\n}\n\n// Adapted from https://developers.cloudflare.com/r2/api/workers/workers-multipart-usage/\nexport const getHandleMultiPartUpload =\n  ({\n    access = defaultR2ClientUploadsAccess,\n    bucket,\n    collections,\n    useCompositePrefixes = false,\n  }: Args): PayloadHandler =>\n  async (req) => {\n    const params = Object.fromEntries(req.searchParams) as R2StorageMultipartUploadHandlerParams\n    const collectionSlug = params.collection\n    const filetype = params.fileType\n\n    const collectionConfig = collections[collectionSlug]\n    if (!collectionConfig) {\n      throw new APIError(`Collection ${collectionSlug} was not found in R2 Storage options`)\n    }\n\n    if (!(await access({ collectionSlug, req }))) {\n      throw new Forbidden(req.t)\n    }\n\n    const collectionPrefix = (typeof collectionConfig === 'object' && collectionConfig.prefix) || ''\n    const { fileKey, sanitizedFilename } = await resolveSignedURLKey({\n      collectionPrefix,\n      collectionSlug,\n      docPrefix: params.docPrefix ?? undefined,\n      filename: params.fileName,\n      req,\n      useCompositePrefixes,\n    })\n\n    const multipartId = params.multipartId\n    const multipartKey = params.multipartKey","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/storage-r2/src/handleMultiPartUpload.ts#L28-L64","documentation":"Thrown inside the R2 multipart-upload handler after it indexes the storage adapter's own `collections` option map (collections[collectionSlug]). Unlike error 380, this checks the R2 adapter configuration, not Payload's global collection registry. A bare APIError (HTTP 500) signals the collection exists in Payload but was never wired into this storage adapter.","triggerScenarios":"The collection slug resolves in req.payload.collections but not in the R2StorageOptions.collections map passed to the adapter — i.e. the collection is registered but the R2 adapter does not have an entry (prefix/options) for it.","commonSituations":"A new upload-enabled collection was added to Payload config but the developer forgot to add it to the R2 adapter's `collections` option; the adapter was mounted on only a subset of upload collections; slug renamed in one place but not the adapter config.","solutions":["Add the missing collection slug to the R2 adapter's `collections` option (e.g. collections: { media: { prefix: 'media' } }).","Confirm the adapter is instantiated with the same collection slugs that perform multipart uploads.","If the collection should not use R2 multipart uploads, prevent the client from requesting that endpoint for it."],"exampleFix":"// before\nconst r2Adapter = new R2Storage({ bucket, collections: { media: { prefix: 'media' } } })\n// client requests ?collection=avatars → throws\n\n// after\nconst r2Adapter = new R2Storage({\n  bucket,\n  collections: {\n    media: { prefix: 'media' },\n    avatars: { prefix: 'avatars' },\n  },\n})","handlingStrategy":"validation","validationCode":"function isConfiguredForR2(slug: string, collections: Record<string, unknown>): boolean {\n  return slug in collections\n}\n\n// guard before the request\nif (!isConfiguredForR2(collectionSlug, r2AdapterCollections)) {\n  throw new Error(`Collection '${collectionSlug}' is not configured on the R2 adapter`)\n}","typeGuard":"function collectionHasR2Config<T extends Record<string, unknown>>(\n  slug: string,\n  collections: T,\n): slug is keyof T & string {\n  return slug in collections\n}","tryCatchPattern":"try {\n  await initiateMultipartUpload({ collection: slug })\n} catch (err) {\n  if (err instanceof APIError && /R2 Storage options/i.test(err.message)) {\n    // prompt operator to add the collection to the R2 adapter config\n  }\n  throw err\n}","preventionTips":["Add a config-time assertion that every upload collection is present in the storage adapter's collections map.","Generate the adapter's collections map from the same source as the Payload collections config.","Document which collections are R2-backed in the project README."],"tags":["r2-storage","upload","config","multipart"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}