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 as UnauthorizedError (HTTP 401) by the experimental _internal_renderField server function when req.user is falsy. This server function renders a single field's custom components on the server and requires an authenticated admin session.

Source

Thrown at packages/ui/src/forms/fieldSchemasToFormState/serverFunctions/renderFieldServerFn.ts:53

   *
   * Examples:
   *   "collection.posts.richText"
   *   "global.siteSettings.content"
   */
  schemaPath: string
}
export type RenderFieldServerFnReturnType = {} & FieldState['customComponents']

/**
 * @experimental - may break in minor releases
 */
export const _internal_renderFieldHandler: ServerFunction<
  RenderFieldServerFnArgs,
  Promise<RenderFieldServerFnReturnType>
  // eslint-disable-next-line @typescript-eslint/require-await
> = async ({ field: fieldArg, initialValue, path, req, schemaPath }) => {
  if (!req.user) {
    throw new UnauthorizedError()
  }

  const [entityType, entitySlug, ...fieldPath] = schemaPath.split('.')

  const schemaMap = getSchemaMap({
    collectionSlug: entityType === 'collection' ? entitySlug : undefined,
    config: req.payload.config,
    globalSlug: entityType === 'global' ? entitySlug : undefined,
    i18n: req.i18n,
  })

  // Provide client schema map as it would have been provided if the target editor field would have been rendered.
  // For lexical, only then will it contain all the lexical-internal entries
  const clientSchemaMap = getClientSchemaMap({
    collectionSlug: entityType === 'collection' ? entitySlug : undefined,
    config: getClientConfig({
      config: req.payload.config,
      i18n: req.i18n,

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Ensure the admin session is active and the cookie reaches the renderField server function.
  2. Gate client-side calls to renderField behind a user check so they aren't issued anonymously.
  3. Wire auth middleware to populate req.user before the server function executes.

Example fix

// before — calling renderField without ensuring auth
const result = await fetchServerFunction('renderField', { schemaPath, path })

// after — verify auth before calling
if (!user) redirect('/login')
const result = await fetchServerFunction('renderField', { schemaPath, path })
Defensive patterns

Strategy: validation

Validate before calling

function isLoggedIn(user: unknown): user is { id: string } {
  return Boolean(user)
}

if (!isLoggedIn(req.user)) {
  throw new Error('Login required to render this field.')
}

Type guard

import { UnauthorizedError } from 'payload'

function isUnauthorized(err: unknown): err is UnauthorizedError {
  return err instanceof UnauthorizedError
}

Try / catch

try {
  await fetchServerFunction('renderField', { field, schemaPath, path })
} catch (err) {
  if (isUnauthorized(err)) {
    redirectToLogin()
    return
  }
  throw err
}

Prevention

When it happens

Trigger: The renderField server function is invoked (e.g. to server-render a field's custom component) while req.user is null — no session, expired session, or the call did not propagate auth.

Common situations: Field renders triggered after session expiry; a custom editor invoking the renderField RPC without forwarding credentials; SSR of a field before auth middleware populates req.user.

Understand the failure class

Related errors


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