payloadcms/payload · error · UnauthorizedError
Unauthorized, you must be logged in to make this request.
Error message
Unauthorized, you must be logged in to make this request.
What it means
Thrown by `canAccessAdmin` when the authenticated user collection defines an `access.admin` function and that function returns a falsy value. This is the primary, customizable admin-access gate -- it runs per-request on admin-protected routes and server functions.
Source
Thrown at packages/payload/src/utilities/canAccessAdmin.ts:24
* Protects admin-only routes, server functions, etc.
* The requesting user must either:
* a. pass the `access.admin` function on the `users` collection, if defined
* b. match the `config.admin.user` property on the Payload config
* c. if no user is present, and there are no users in the system, allow access (for first user creation)
* @throws {Error} Throws an `Unauthorized` error if access is denied that can be explicitly caught
*/
export const canAccessAdmin = async ({ req }: { req: PayloadRequest }) => {
const incomingUserSlug = req.user?.collection
const adminUserSlug = req.payload.config.admin.user
if (incomingUserSlug) {
const adminAccessFn = req.payload.collections[incomingUserSlug]?.config.access?.admin
if (adminAccessFn) {
const canAccess = await adminAccessFn({ slug: incomingUserSlug, req })
if (!canAccess) {
throw new UnauthorizedError()
}
// Match the user collection to the global admin config
} else if (adminUserSlug !== incomingUserSlug) {
throw new UnauthorizedError()
}
} else {
const hasUsers = await req.payload.find({
collection: adminUserSlug,
depth: 0,
limit: 1,
pagination: false,
})
// If there are users, we should not allow access because of `/create-first-user`
if (hasUsers.docs.length) {
throw new UnauthorizedError()
}
}View on GitHub (pinned to 00c58b35c0)
Solutions
- Inspect the collection `access.admin` function logic and verify the user document satisfies its conditions.
- Ensure the user document has the role/permission field the function checks.
- Test the function in isolation with the actual `req.user` object.
- Update the `access.admin` implementation if the role model changed.
Example fix
// before
access: {
admin: ({ req }) => req.user.role === 'admin', // user has 'roles' array, not 'role'
}
// after
access: {
admin: ({ req }) => Array.isArray(req.user?.roles) && req.user.roles.includes('admin'),
} Defensive patterns
Strategy: validation
Validate before calling
// Before making the admin request, verify the user passes the access.admin check
const adminAccessFn = collectionConfig.access?.admin
if (adminAccessFn) {
const ok = await adminAccessFn({ slug: user.collection, req: syntheticReq })
if (!ok) throw new Error('User fails access.admin check')
} Try / catch
try {
await adminAction()
} catch (e) {
if (e instanceof UnauthorizedError) {
// inspect access.admin logic; ensure user has required role/permission
} else throw e
} Prevention
- Define access.admin explicitly on every auth collection that needs admin gating.
- Unit-test the access.admin function against representative user documents.
- Ensure user documents have the role/permission fields the function checks.
- Handle UnauthorizedError gracefully in the UI with a login redirect.
When it happens
Trigger: A logged-in user whose collection config includes `access: { admin: ({ req }) => boolean }` makes a request to an admin-gated route or server function, and the function evaluates to `false` (e.g. a role check fails).
Common situations: The `access.admin` function checks a role/permission field that is missing or wrong on the user document; a migration changed the user role field name; the function has a bug (e.g. `req.user.role === 'writer'` when the field is `req.user.roles` array); the user was created before the access logic was added and lacks the required attribute.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- This action will lock you out of this preset.
- 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/31036a16adeb5192.
Report an issue: GitHub.