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
- Keep at least one read OR update grant for yourself in the new access config — the lockout only triggers when BOTH fail.
- Adjust the `access.update`/`access.read` functions so the current user still passes after the change.
- 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
- Always retain read OR update access for the acting user in preset access functions.
- In the UI, disable 'save' if the access editor would remove all of the user's grants.
- Write access-function tests asserting the acting role still passes after a change.
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
- Unauthorized, you must be logged in to make this request.
- Collection ${args.collection.config.slug} has disabled bulk
- 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/6db0af471ba53d23.
Report an issue: GitHub.