payloadcms/payload · error · ValidationError

Username or email is required

Error message

Username or email is required

What it means

A Payload `ValidationError` raised by `ensureUsernameOrEmail` during auth collection create/update. It fires when the operation would leave the document with neither a username nor an email — for example clearing `email` on a doc that has no username, or clearing `username` on a doc that has no email, or creating a doc with both absent. The error reports two field-level errors (username and email) so the UI can flag both.

Source

Thrown at packages/payload/src/auth/ensureUsernameOrEmail.ts:57

    if (operation === 'create' && !data.email && !data.username) {
      missingFields = true
    } else if (operation === 'update') {
      // prevent clearing both email and username
      if ('email' in data && !data.email && 'username' in data && !data.username) {
        missingFields = true
      }
      // prevent clearing email if no username
      if ('email' in data && !data.email && !originalDoc.username && !data?.username) {
        missingFields = true
      }
      // prevent clearing username if no email
      if ('username' in data && !data.username && !originalDoc.email && !data?.email) {
        missingFields = true
      }
    }

    if (missingFields) {
      throw new ValidationError(
        {
          collection: collectionSlug,
          errors: [
            {
              message: 'Username or email is required',
              path: 'username',
            },
            {
              message: 'Username or email is required',
              path: 'email',
            },
          ],
        },
        req.t,
      )
    }
  }

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Ensure at least one of `username` or `email` is non-empty after the operation: before clearing email, set a username (and vice versa).
  2. If you legitimately want accounts with no contact identifier, disable this guard via a custom `ensureUsernameOrEmail` override only if the schema permits it.
  3. In admin forms, make at least one of the two fields required at the form level so the request never reaches this guard.

Example fix

// before — clearing email on an account with no username
await payload.update({ collection: 'users', id, data: { email: '' } })

// after — set a username first, then clear email
await payload.update({ collection: 'users', id, data: { username: 'u' + id, email: '' } })
Defensive patterns

Strategy: validation

Validate before calling

function hasIdentifier(data, original) {
  const willHaveUsername = data.username ?? original?.username
  const willHaveEmail = data.email ?? original?.email
  return Boolean(willHaveUsername || willHaveEmail)
}

Try / catch

try {
  await payload.update({ collection: 'users', id, data })
} catch (e) {
  if (e instanceof ValidationError && e.data?.errors?.some(er => er.message === 'Username or email is required')) {
    // ensure username or email stays non-empty, then retry
  }
  throw e
}

Prevention

When it happens

Trigger: PATCH/PUT on a users collection setting `email: ''` (or null) when the document's `username` is also empty; creating a user with `{ username: '', email: '' }`; the admin UI clearing the email field on a username-less account. Triggered regardless of which field is being mutated, as long as the end state has no identifier.

Common situations: A collection configured with `auth.loginWithUsername: { allowEmailLogin: false }` where the UI still lets users blank both; bulk imports that omit both fields; a custom update flow that nulls email for GDPR/privacy without first ensuring a username exists.

Related errors


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