payloadcms/payload · error · Forbidden
error:notAllowedToPerformAction
Error message
error:notAllowedToPerformAction
What it means
Thrown at the top of `verifyEmailOperation` when `collection.config.auth.disableLocalStrategy` is true. Email verification is a local-strategy feature, so it is refused for external-strategy collections. `Forbidden` (HTTP 403).
Source
Thrown at packages/payload/src/auth/operations/verifyEmail.ts:22
import type { PayloadRequest } from '../../types/index.js'
import { APIError, Forbidden } from '../../errors/index.js'
import { appendNonTrashedFilter } from '../../utilities/appendNonTrashedFilter.js'
import { commitTransaction } from '../../utilities/commitTransaction.js'
import { initTransaction } from '../../utilities/initTransaction.js'
import { killTransaction } from '../../utilities/killTransaction.js'
export type Args = {
collection: Collection
req: PayloadRequest
token: string
}
export const verifyEmailOperation = async (args: Args): Promise<boolean> => {
const { collection, req, token } = args
if (collection.config.auth.disableLocalStrategy) {
throw new Forbidden(req.t)
}
if (!Object.prototype.hasOwnProperty.call(args, 'token')) {
throw new APIError('Missing required data.', httpStatus.BAD_REQUEST)
}
try {
const shouldCommit = await initTransaction(req)
const where = appendNonTrashedFilter({
enableTrash: Boolean(collection.config.trash),
trash: false,
where: {
_verificationToken: { equals: token },
},
})
const user = await req.payload.db.findOne<any>({
collection: collection.config.slug,View on GitHub (pinned to 00c58b35c0)
Solutions
- Only call verifyEmail on local-strategy collections (`auth.disableLocalStrategy: false`).
- For external-strategy collections, handle email verification in the IdP.
- If you intend local email verification, ensure `auth.verify` is set and `disableLocalStrategy` is false.
Example fix
// before
await payload.verifyEmail({ collection, token, req })
// after
if (!collectionConfig.auth.disableLocalStrategy) {
await payload.verifyEmail({ collection, token, req })
} Defensive patterns
Strategy: validation
Validate before calling
// Skip verifyEmail for external-strategy collections
if (collection.config.auth.disableLocalStrategy) {
throw new Error('Email verification is unavailable for this collection')
}
await payload.verifyEmail({ collection, token, req }) Type guard
function supportsEmailVerification(cfg: CollectionConfig): boolean {
return !cfg.auth?.disableLocalStrategy && !!cfg.auth?.verify
} Try / catch
if (collection.config.auth.disableLocalStrategy) {
// verification handled by the IdP
} else {
await payload.verifyEmail({ collection, token, req })
} Prevention
- Branch verification flows on `disableLocalStrategy`.
- Only enable `auth.verify` on local-strategy collections.
- Document which collections perform their own email verification.
When it happens
Trigger: A `GET/POST /api/<collection>/verify/<token>` (or Local API `payload.verifyEmail`) is invoked on a collection with `auth: { disableLocalStrategy: true }` and the guard fires before token lookup.
Common situations: Verification links sent for an SSO collection; a shared email-verification pipeline that doesn't branch on strategy; misconfiguration mixing `verify` with `disableLocalStrategy`.
Related errors
- error:notAllowedToPerformAction
- error:notAllowedToPerformAction
- error:notAllowedToPerformAction
- Missing required data.
- Verification token is invalid.
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/651014ae0e1a01a3.
Report an issue: GitHub.