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 the preferences `deleteOperation` when `req.user` is falsy. Preferences are per-user records keyed by `user.value`/`user.relationTo`, so deleting one requires an authenticated user to scope the where clause. No user means the operation cannot be safely scoped.
Source
Thrown at packages/payload/src/preferences/operations/delete.ts:17
import type { Document, Where } from '../../types/index.js'
import type { PreferenceRequest } from '../types.js'
import { NotFound } from '../../errors/NotFound.js'
import { UnauthorizedError } from '../../errors/UnauthorizedError.js'
import { preferencesCollectionSlug } from '../config.js'
export async function deleteOperation(args: PreferenceRequest): Promise<Document> {
const {
key,
req: { payload },
req,
user,
} = args
if (!user) {
throw new UnauthorizedError(req.t)
}
const where: Where = {
and: [
{ key: { equals: key } },
{ 'user.value': { equals: user.id } },
{ 'user.relationTo': { equals: user.collection } },
],
}
const result = await payload.db.deleteOne({
collection: preferencesCollectionSlug,
req,
where,
})
if (result) {
return resultView on GitHub (pinned to 00c58b35c0)
Solutions
- Authenticate the request first so `req.user` is populated.
- When using the Local API, pass a req with a user: `payload.delete({ collection: 'payload-preferences', id, req: authenticatedReq })`.
- If this is intentional trusted code, use `overrideAccess: true` only where appropriate (preferences still require a user to scope).
Example fix
// before
await payload.delete({ collection: 'payload-preferences', id, req })
// after
if (!req.user) throw new Error('login required')
await payload.delete({ collection: 'payload-preferences', id, req }) Defensive patterns
Strategy: validation
Validate before calling
if (!req.user) {
return res.status(401).json({ error: 'Authentication required' })
}
await payload.delete({ collection: 'payload-preferences', id, req }) Type guard
import type { PayloadRequest, User } from 'payload'
function isAuthenticated(req: PayloadRequest): req is PayloadRequest & { user: User } {
return Boolean(req.user)
}
if (!isAuthenticated(req)) throw new UnauthorizedError(req.t) Try / catch
try {
await payload.delete({ collection: 'payload-preferences', id, req })
} catch (err) {
if (err instanceof UnauthorizedError || err.statusCode === 401) {
// prompt login / return 401 to the client
} else throw err
} Prevention
- Gate preference routes behind auth middleware at the API layer.
- When using the Local API, always forward the authenticated `req`.
- Add a UI guard so preference actions are only rendered for logged-in users.
When it happens
Trigger: Calling the preferences delete endpoint (or `payload.delete({ collection: 'payload-preferences', ... })`) on a request with no authenticated user, or with `overrideAccess: false` and a req lacking `user`.
Common situations: Hitting `/api/payload-preferences/<key>` without a session cookie/token; a server-to-server call that forgot to attach `req.user`; calling the Local API delete without passing an authenticated `req`.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Unauthorized, you must be logged in to make this request.
- You are not allowed to perform this action.
- 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/bad4bc42eef5a1ac.
Report an issue: GitHub.