payloadcms/payload · error · APIError
Incorrect collection
Error message
Incorrect collection
What it means
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.
Source
Thrown at packages/payload/src/auth/operations/logout.ts:31
allSessions?: boolean
collection: Collection
req: PayloadRequest
}
export const logoutOperation = async (incomingArgs: Arguments): Promise<boolean> => {
let args = incomingArgs
const {
allSessions,
collection: { config: collectionConfig },
req: { user },
req,
} = incomingArgs
if (!user) {
throw new APIError('No User', httpStatus.BAD_REQUEST)
}
if (user.collection !== collectionConfig.slug) {
throw new APIError('Incorrect collection', httpStatus.FORBIDDEN)
}
const shouldCommit = await initTransaction(req)
try {
if (collectionConfig.hooks?.afterLogout?.length) {
for (const hook of collectionConfig.hooks.afterLogout) {
args =
(await hook({
collection: args.collection?.config,
context: req.context,
req,
})) || args
}
}
if (collectionConfig.auth.disableLocalStrategy !== true && collectionConfig.auth.useSessions) {
const where = appendNonTrashedFilter({View on GitHub (pinned to 00c58b35c0)
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.
Example fix
// before
await payload.logout({ collection: 'admins', req })
// after
await payload.logout({ collection: req.user.collection, req }) Defensive patterns
Strategy: validation
Validate before calling
// Use the collection the token actually belongs to
const slug = req.user?.collection ?? targetCollection
if (req.user && req.user.collection !== slug) {
throw new Error(`Logout target ${slug} does not match authenticated collection ${req.user.collection}`)
} Type guard
function userMatchesCollection(user: User, slug: string): boolean {
return user.collection === slug
} Try / catch
try {
await payload.logout({ collection: req.user.collection, req })
} catch (e) {
if (e instanceof APIError && e.message === 'Incorrect collection') {
// re-route logout to the correct collection slug
} else throw e
} Prevention
- 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.
When it happens
Trigger: 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'`.
Common situations: 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.
Related errors
- No User
- Verification token is invalid.
- You are not allowed to perform this action.
- You are not allowed to perform this action.
- You are not allowed to perform this action.
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/12c28edbac067361.
Report an issue: GitHub.