payloadcms/payload · error · APIError

This action will lock you out of this preset.

Error message

This action will lock you out of this preset.

What it means

Thrown by `preventLockout` with HTTP 403 when an attempted query-preset change would remove the user's own ability to read AND update the preset. The function simulates the change by writing a temp preset and trying to read/update it with `overrideAccess: false`; if both fail, it aborts to keep the user from locking themselves out. The thrown APIError has `isSensitive=true`.

Source

Thrown at packages/payload/src/query-presets/preventLockout.ts:75

        req,
        user: req.user,
      })

      canRead = true

      await req.payload.update({
        id: tempPreset.id,
        collection: queryPresetsCollectionSlug,
        data: tempPreset,
        overrideAccess: false,
        req,
        user: req.user,
      })

      canUpdate = true
    } catch (_err) {
      if (!canRead || !canUpdate) {
        throw new APIError('This action will lock you out of this preset.', 403, {}, true)
      }
    } finally {
      if (transaction) {
        await killTransaction(req)
      } else {
        // delete the temp record
        await req.payload.delete({
          id: tempPreset.id,
          collection: queryPresetsCollectionSlug,
          req,
        })
      }
    }
  }

  return true as unknown as true
}

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Keep at least one read OR update grant for yourself in the new access config — the lockout only triggers when BOTH fail.
  2. Adjust the `access.update`/`access.read` functions so the current user still passes after the change.
  3. Use an admin/superuser context (`overrideAccess`) only if lockout recovery is intentional, and document it.

Example fix

// before
access: { update: () => false } // locks everyone out

// after
access: {
  update: ({ req: { user } }) => Boolean(user),
  read: ({ req: { user } }) => Boolean(user),
}
Defensive patterns

Strategy: validation

Validate before calling

import { APIError } from 'payload'

async function canReadAndUpdateAfterChange(payload, presetId, req): Promise<boolean> {
  // mimic preventLockout: confirm at least read OR update still holds
  try {
    await payload.findByID({ collection: 'query-presets', id: presetId, overrideAccess: false, req })
    return true
  } catch {
    return false
  }
}

// before applying the preset change, warn the user if it would lock them out

Try / catch

try {
  await payload.update({ collection: 'query-presets', id, data, req })
} catch (err) {
  if (err instanceof APIError && err.message.includes('lock you out')) {
    // surface a friendly warning: 'keep at least read or update for yourself'
  } else throw err
}

Prevention

When it happens

Trigger: Editing a query preset's `access` control or ownership so that the current user would no longer satisfy `read` and `update` access — e.g. changing access to a role the user lacks, or reassigning to another user.

Common situations: An admin narrows preset access and accidentally excludes their own role; changing the preset's user/relationship field to someone else; misconfigured access function that returns false for the acting user.

Related errors


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