{"record":{"id":"046c35855ce3a3f7","repo":"payloadcms/payload","slug":"email-or-username-is-required","errorCode":null,"errorMessage":"Email or username is required.","messagePattern":"Email or username is required\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/payload/src/auth/serverFunctions/login.ts","lineNumber":56,"sourceCode":"  email,\n  password,\n  serverAdapter,\n  username,\n}: LoginArgs<TSlug>): Promise<LoginResult<TSlug>> {\n  const payload = await getPayload({ config, cron: true })\n\n  const authConfig = payload.collections[collection]?.config.auth\n\n  if (!authConfig) {\n    throw new Error(`No auth config found for collection: ${collection}`)\n  }\n\n  const loginWithUsername = authConfig.loginWithUsername ?? false\n\n  if (loginWithUsername) {\n    if (loginWithUsername.allowEmailLogin) {\n      if (!email && !username) {\n        throw new Error('Email or username is required.')\n      }\n    } else {\n      if (!username) {\n        throw new Error('Username is required.')\n      }\n    }\n  } else {\n    if (!email) {\n      throw new Error('Email is required.')\n    }\n  }\n\n  let loginData\n\n  if (loginWithUsername) {\n    loginData = username ? { password, username } : { email, password }\n  } else {\n    loginData = { email, password }","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/payload/src/auth/serverFunctions/login.ts#L38-L74","documentation":"Thrown in the server-function `login` when the collection uses `loginWithUsername` with `allowEmailLogin: true` and neither `email` nor `username` is supplied. Payload cannot identify the account with zero identifiers. Plain `Error` (no HTTP status).","triggerScenarios":"Calling `login({ collection, password, serverAdapter })` without `email` or `username`; both fields are empty strings; the adapter's caller destructured only `password`. With `allowEmailLogin`, exactly one of email/username is required.","commonSituations":"A login form that conditionally renders email/username but submits when both are blank; the union type `LoginArgs` is bypassed by a `as any` cast; the frontend forgot to include the identifier field in the POST body that the adapter reads.","solutions":["Pass exactly one identifier: `login({ collection, password, email, serverAdapter })` or `login({ collection, password, username, serverAdapter })`.","Validate that at least one of email/username is non-empty before calling.","Respect the `LoginArgs` union type (`{ email } | { username }`) so TypeScript enforces the either/or."],"exampleFix":"// before\nawait login({ collection, password, serverAdapter })\n// after\nawait login({ collection, password, email: identifier, serverAdapter })","handlingStrategy":"validation","validationCode":"// Ensure exactly one identifier is provided\nif (!email && !username) {\n  throw new Error('Email or username is required')\n}\nawait login({\n  collection,\n  config,\n  password,\n  ...(email ? { email } : { username }),\n  serverAdapter,\n})","typeGuard":"function hasLoginIdentifier(args: { email?: string; username?: string }): boolean {\n  return !!args.email || !!args.username\n}","tryCatchPattern":"// Plain Error (not APIError) — validate before calling instead\nif (!email && !username) {\n  // prompt the user for an identifier\n} else {\n  await login({ collection, config, password, ...(email ? { email } : { username }), serverAdapter })\n}","preventionTips":["Respect the `LoginArgs` union type (`{ email } | { username }`) — avoid `as any`.","Validate at least one identifier is non-empty before calling.","Submit the identifier the user actually entered from the form."],"tags":["auth","login","validation","server-function"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}