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
- Ensure at least one of `username` or `email` is non-empty after the operation: before clearing email, set a username (and vice versa).
- If you legitimately want accounts with no contact identifier, disable this guard via a custom `ensureUsernameOrEmail` override only if the schema permits it.
- 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
- Before clearing email, set a username (and vice versa).
- Make at least one identifier required at the form layer.
- In import scripts, populate one identifier for every row.
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
- validation:required
- Username is required.
- Email is required.
- A user with the given username is already registered.
- A user with the given email is already registered.
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/9987b3a0510dace5.
Report an issue: GitHub.