nextauthjs/next-auth · error
Missing email from request body.
Error message
Missing email from request body.
What it means
Before sending a sign-in email, Auth.js normalizes the email from the request body via defaultNormalizer. If the body contains no email (undefined or empty string), this plain Error is thrown because there is no address to send a verification token to.
Source
Thrown at packages/core/src/lib/actions/signin/send-token.ts:95
const createToken = adapter!.createVerificationToken?.({
identifier: email,
token: await createHash(`${token}${secret}`),
expires,
})
await Promise.all([sendRequest, createToken])
return {
redirect: `${baseUrl}/verify-request?${new URLSearchParams({
provider: provider.id,
type: provider.type,
})}`,
}
}
export function defaultNormalizer(email?: string) {
if (!email) throw new Error("Missing email from request body.")
// Apply Unicode NFKC normalization *before* validation. Without this, a
// character that is a homoglyph of `@` (e.g. U+FF20 FULLWIDTH COMMERCIAL AT)
// passes the single-`@` check below, but can later be canonicalized to an
// ASCII `@` by a downstream address parser, splitting the address into
// multiple recipients. Normalizing first ensures any such homoglyph is
// turned into a real `@` and rejected by the checks below.
const trimmedEmail = email.normalize("NFKC").toLowerCase().trim()
// Reject email addresses with quotes to prevent address parser confusion
// This prevents attacks like "attacker@evil.com"@victim.com
if (trimmedEmail.includes('"')) {
throw new Error("Invalid email address format.")
}
// Get the first two elements only,
// separated by `@` from user input.
let [local, domain] = trimmedEmail.split("@")View on GitHub (pinned to a1a16a5a77)
Solutions
- Ensure the POST body includes an 'email' field: use FormData or URLSearchParams with key 'email' and a non-empty value
- Add client-side required/email-format validation before submitting the sign-in form
- If posting JSON, confirm your route forwards it correctly — Auth.js expects form-encoded bodies by default
- Verify the input element's name attribute is exactly 'email'
Example fix
// before
await fetch('/api/auth/signin/email', { method: 'POST', body: JSON.stringify({ mail: email }) });
// after
const body = new URLSearchParams({ email, csrfToken });
await fetch('/api/auth/signin/email', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
credentials: 'include',
body,
}); Defensive patterns
Strategy: validation
Validate before calling
function canSubmitEmail(v: unknown): v is string {
return typeof v === 'string' && v.trim().length > 0 && v.includes('@');
}
if (!canSubmitEmail(formData.get('email'))) throw new Error('Email is required'); Type guard
function isNonEmptyEmail(v: unknown): v is string {
return typeof v === 'string' && v.trim() !== '';
} Try / catch
try {
await signIn('email', { email });
} catch (e) {
if (/Missing email from request body/.test(String(e))) {
// re-render the form with a 'email is required' message
}
} Prevention
- Mark the email input required and validate before submit
- Use the exact body key 'email' with form-urlencoded or FormData encoding
- Never send a template placeholder like '${email}' unrendered
- Add an integration test that posts a real email to /api/auth/signin/email
When it happens
Trigger: POSTing to /api/auth/signin/email (or provider id) with a body missing the email field, an empty email, or a field named differently than the library expects (the form key must be 'email'); JSON bodies that fail to parse into { email }.
Common situations: Custom sign-in form submitting without the email input filled or with a misspelled input name; sending JSON instead of form-urlencoded where the server expects urlencoded body; server actions or fetch calls that forget to append email to FormData; email-only input validation missing on the client.
Related errors
- Invalid email address format.
- malformed Mailgun domain
- No user id.
- User id is required
- credential id is required
AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28).
Data as JSON: /api/errors/16bf36db0c4a6d27.
Report an issue: GitHub.