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
The slug field's server-side slugify handler throws UnauthorizedError when `req.user` is absent. Generating a unique slug probes the collection for collisions via `getUniqueFieldValue`, which requires an authenticated admin session, so the handler rejects anonymous requests before reading field config or touching the DB. This is a deliberate auth gate, not an accidental failure.
Source
Thrown at packages/ui/src/utilities/slugify.ts:33
/**
* This server function is directly related to the {@link https://payloadcms.com/docs/fields/slug | Slug Field}.
* This is a server function that is used to invoke the user's custom slugify function from the client.
* This pattern is required, as there is no other way for us to pass their function across the client-server boundary.
* - Not through props
* - Not from a server function defined within a server component (see below)
* When a server function contains non-serializable data within its closure, it gets passed through the boundary (and breaks).
* The only way to pass server functions to the client (that contain non-serializable data) is if it is globally defined.
* But we also cannot define this function alongside the server component, as we will not have access to their custom slugify function.
* See `ServerFunctionsProvider` for more details.
*/
export const slugifyHandler: ServerFunction<
SlugifyServerFunctionArgs,
Promise<ReturnType<Slugify>>
> = async (args) => {
const { id, collectionSlug, data, globalSlug, locale, path, req, valueToSlugify } = args
if (!req.user) {
throw new UnauthorizedError()
}
const docConfig = collectionSlug
? req.payload.collections[collectionSlug]?.config
: globalSlug
? req.payload.config.globals.find((g) => g.slug === globalSlug)
: null
if (!docConfig) {
throw new Error()
}
const { field } = getFieldByPath({
config: req.payload.config,
fields: docConfig.flattenedFields,
path,
})
View on GitHub (pinned to 00c58b35c0)
Solutions
- Ensure the user is logged in and the session is still valid before editing a slug field.
- Verify the auth cookie is sent with the server-function request (credentials: 'include' / same-origin).
- Confirm the configured auth strategy populates `req.user` for admin routes.
- Re-authenticate the user and retry the slug generation.
Defensive patterns
Strategy: validation
Validate before calling
if (!req.user) {
// surface 'login required' / redirect to /admin/login before invoking slugify
} Type guard
function isAuthenticated<
R extends { user?: unknown },
>(req: R): req is R & { user: NonNullable<R['user']> } {
return !!req.user
} Try / catch
import { UnauthorizedError } from 'payload'
try {
await slugify(args)
} catch (err) {
if (err instanceof UnauthorizedError) {
// session expired - prompt re-login, then retry
} else {
throw err
}
} Prevention
- Send credentials with all admin server-function requests.
- Surface session-expiry UI and re-authenticate before retrying slug generation.
- Gate slug-generating inputs on a live session check in the admin client.
- Confirm the auth strategy populates `req.user` for admin routes.
When it happens
Trigger: Slug auto-generation triggered after the admin session expired, the auth cookie not sent on the server-function fetch, a custom auth strategy that does not populate `req.user`, accessing the admin slug field while logged out.
Common situations: Long-idle admin tabs whose session lapsed, cross-origin server-function requests sent without credentials, auth plugin misconfiguration leaving `req.user` undefined, load-balancer/proxy stripping cookies.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Unauthorized
- Unauthorized
- Unauthorized
- Unauthorized
- Unauthorized, you must be logged in to make this request.
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/b49fd91993ae8c4d.
Report an issue: GitHub.