payloadcms/payload · error · Error
Username is required.
Error message
Username is required.
What it means
Thrown by the framework-agnostic `login` server function when the target auth collection has `auth.loginWithUsername` enabled but `loginWithUsername.allowEmailLogin` is falsy, and the caller did not supply a `username`. It is a pre-credential input guard: login is username-only for this collection, so Payload refuses to proceed without one.
Source
Thrown at packages/payload/src/auth/serverFunctions/login.ts:60
}: LoginArgs<TSlug>): Promise<LoginResult<TSlug>> {
const payload = await getPayload({ config, cron: true })
const authConfig = payload.collections[collection]?.config.auth
if (!authConfig) {
throw new Error(`No auth config found for collection: ${collection}`)
}
const loginWithUsername = authConfig.loginWithUsername ?? false
if (loginWithUsername) {
if (loginWithUsername.allowEmailLogin) {
if (!email && !username) {
throw new Error('Email or username is required.')
}
} else {
if (!username) {
throw new Error('Username is required.')
}
}
} else {
if (!email) {
throw new Error('Email is required.')
}
}
let loginData
if (loginWithUsername) {
loginData = username ? { password, username } : { email, password }
} else {
loginData = { email, password }
}
const collectionConfig = payload.collections[collection]!
View on GitHub (pinned to 00c58b35c0)
Solutions
- Pass a non-empty `username` in the `login` call.
- Confirm the collection's `auth.loginWithUsername.allowEmailLogin` value matches what your form collects.
- If the form collects email, set `allowEmailLogin: true` in the collection's auth config.
Example fix
// before
await login({ collection: 'users', config, password, email: form.email, serverAdapter })
// after
await login({ collection: 'users', config, password, username: form.username, serverAdapter }) Defensive patterns
Strategy: validation
Validate before calling
function needsUsername(loginWithUsername) {
return !!loginWithUsername && !loginWithUsername.allowEmailLogin
}
function validateUsernameLogin(args) {
if (needsUsername(args.loginWithUsername) && !args.username?.trim()) {
return { ok: false, message: 'Username is required.' }
}
return { ok: true }
} Type guard
function hasUsername(args): args is { username: string } {
return typeof args?.username === 'string' && args.username.trim().length > 0
} Prevention
- Match your login form fields to the collection's `loginWithUsername` config.
- Trim and check for empty strings, not just undefined.
- Rely on the `LoginArgs` discriminated union for compile-time enforcement.
When it happens
Trigger: Calling `login({ collection, config, password, serverAdapter })` against a collection configured with `loginWithUsername: true` (or `{ allowEmailLogin: false }`) while omitting `username`, or passing `username: ''`. The `LoginArgs` discriminated union enforces this at compile time, but loose JS callers, form handlers, or adapters forwarding empty strings bypass it.
Common situations: A login form that always submits `email` but targets a username-only collection; the collection's auth config was switched from email to username-only without updating the form; an adapter that forwards `undefined`/empty for the username field.
Related errors
- validation:required
- Username or email is required
- Email or username is required.
- Email is required.
- A user with the given username is already registered.
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/027599b48011addf.
Report an issue: GitHub.