{"record":{"id":"12c28edbac067361","repo":"payloadcms/payload","slug":"incorrect-collection","errorCode":null,"errorMessage":"Incorrect collection","messagePattern":"Incorrect collection","errorType":"exception","errorClass":"APIError","httpStatus":403,"severity":"error","filePath":"packages/payload/src/auth/operations/logout.ts","lineNumber":31,"sourceCode":"  allSessions?: boolean\n  collection: Collection\n  req: PayloadRequest\n}\n\nexport const logoutOperation = async (incomingArgs: Arguments): Promise<boolean> => {\n  let args = incomingArgs\n  const {\n    allSessions,\n    collection: { config: collectionConfig },\n    req: { user },\n    req,\n  } = incomingArgs\n\n  if (!user) {\n    throw new APIError('No User', httpStatus.BAD_REQUEST)\n  }\n  if (user.collection !== collectionConfig.slug) {\n    throw new APIError('Incorrect collection', httpStatus.FORBIDDEN)\n  }\n\n  const shouldCommit = await initTransaction(req)\n\n  try {\n    if (collectionConfig.hooks?.afterLogout?.length) {\n      for (const hook of collectionConfig.hooks.afterLogout) {\n        args =\n          (await hook({\n            collection: args.collection?.config,\n            context: req.context,\n            req,\n          })) || args\n      }\n    }\n\n    if (collectionConfig.auth.disableLocalStrategy !== true && collectionConfig.auth.useSessions) {\n      const where = appendNonTrashedFilter({","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/payload/src/auth/operations/logout.ts#L13-L49","documentation":"Thrown when `user.collection !== collectionConfig.slug` — the authenticated user's JWT was minted for a different collection than the one the logout route targets. Payload supports multiple auth collections, and each logout endpoint is scoped to one collection slug. Mismatch is rejected with HTTP 403. This prevents cross-collection session tampering.","triggerScenarios":"A user authenticated against the `customers` collection hits `POST /api/admins/logout` (or vice-versa). Programmatically: `payload.logout({ collection: 'admins', req })` where `req.user.collection === 'customers'`.","commonSituations":"A monorepo/frontend hard-codes the wrong collection slug in the logout URL after splitting auth into multiple collections; copy-pasting a logout call across collection contexts; a JWT from a staging environment's other collection leaking into the client.","solutions":["Use the same collection slug the user logged in with: derive it from `req.user.collection` instead of hard-coding.","Ensure the frontend logout call targets the collection that owns the token, e.g. `/api/${userCollection}/logout`.","If calling the Local API, read `req.user.collection` and pass that slug."],"exampleFix":"// before\nawait payload.logout({ collection: 'admins', req })\n// after\nawait payload.logout({ collection: req.user.collection, req })","handlingStrategy":"validation","validationCode":"// Use the collection the token actually belongs to\nconst slug = req.user?.collection ?? targetCollection\nif (req.user && req.user.collection !== slug) {\n  throw new Error(`Logout target ${slug} does not match authenticated collection ${req.user.collection}`)\n}","typeGuard":"function userMatchesCollection(user: User, slug: string): boolean {\n  return user.collection === slug\n}","tryCatchPattern":"try {\n  await payload.logout({ collection: req.user.collection, req })\n} catch (e) {\n  if (e instanceof APIError && e.message === 'Incorrect collection') {\n    // re-route logout to the correct collection slug\n  } else throw e\n}","preventionTips":["Derive the logout collection from `req.user.collection`, never hard-code it.","Keep a single source of truth for the active auth collection in the frontend.","When supporting multiple auth collections, branch all auth endpoints on the active one."],"tags":["auth","logout","multi-collection","forbidden"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}