payloadcms/payload · error · Forbidden

You are not allowed to perform this action.

Error message

You are not allowed to perform this action.

What it means

In `findVersionByIDOperation`, if the version is not found AND `hasWhereAccess` is true, it throws `Forbidden`. The user's `access.readVersions` returned a where-constraint that excluded this version, so access is denied.

Source

Thrown at packages/payload/src/collections/operations/findVersionByID.ts:129

    const versionsQuery = await payload.db.findVersions<TData>({
      collection: collectionConfig.slug,
      limit: 1,
      locale: locale!,
      pagination: false,
      req,
      select,
      where: fullWhere,
    })

    let result = versionsQuery.docs[0]!

    if (!result) {
      if (!disableErrors) {
        if (!hasWhereAccess) {
          throw new NotFound(req.t)
        }
        if (hasWhereAccess) {
          throw new Forbidden(req.t)
        }
      }

      return null!
    }

    if (!result.version) {
      // Fallback if not selected
      ;(result as any).version = {}
    }

    // /////////////////////////////////////
    // beforeRead - Collection
    // /////////////////////////////////////

    if (collectionConfig.hooks?.beforeRead?.length) {
      for (const hook of collectionConfig.hooks.beforeRead) {
        result.version =

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Ensure the user has `readVersions` access for that document.
  2. Use `overrideAccess: true` in privileged contexts.
  3. Adjust the `access.readVersions` function if it is too restrictive.

Example fix

// before
await payload.findVersionByID({ collection: 'posts', id })
// after (privileged)
await payload.findVersionByID({ collection: 'posts', id, overrideAccess: true })
Defensive patterns

Strategy: try-catch

Type guard

function isForbidden(e): boolean {
  return e?.statusCode === 403 || e?.name === 'Forbidden'
}

Try / catch

try {
  return await payload.findVersionByID({ collection, id })
} catch (e) {
  if (isForbidden(e)) return null
  throw e
}

Prevention

When it happens

Trigger: `findVersionByID` where the user's `access.readVersions` returns a where clause and no version matches both the requested ID and that access constraint.

Common situations: Role-based version access; a user lacking permission to view versions of another user's documents.

Related errors


AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12). Data as JSON: /api/errors/2dcba6786a6ed5c0. Report an issue: GitHub.