Kareadita/Kavita · error · KavitaException
errors.oidc.missing-email
Error message
errors.oidc.missing-email
What it means
Thrown in LoginOrCreate after a new (unknown oidcId) user passes the NameIdentifier check but the principal has no ClaimTypes.Email. Kavita requires an email to either match an existing account or build a new one; without it the flow cannot proceed. The 'email' scope being absent is the usual cause.
Source
Thrown at Kavita.Services/OidcService.cs:87
var oidcId = principal.FindFirstValue(ClaimTypes.NameIdentifier);
if (string.IsNullOrEmpty(oidcId))
{
throw new KavitaException("errors.oidc.missing-external-id");
}
var user = await unitOfWork.UserRepository.GetByOidcId(oidcId, AppUserIncludes.UserPreferences | AppUserIncludes.SideNavStreams, ct);
if (user != null)
{
await SyncUserSettings(request, settings, principal, user);
return user;
}
var email = principal.FindFirstValue(ClaimTypes.Email);
if (string.IsNullOrEmpty(email))
{
throw new KavitaException("errors.oidc.missing-email");
}
if (settings.RequireVerifiedEmail && !principal.HasVerifiedEmail())
{
throw new KavitaException("errors.oidc.email-not-verified");
}
user = await unitOfWork.UserRepository.GetUserByEmailAsync(email, AppUserIncludes.UserPreferences | AppUserIncludes.SideNavStreams, ct);
if (user != null)
{
// Don't allow taking over accounts
// This could happen if the user changes their email in OIDC, and then someone else uses the old one
if (!string.IsNullOrEmpty(user.OidcId))
{
throw new KavitaException("errors.oidc.email-in-use");
}
View on GitHub (pinned to 9c3e540000)
Solutions
- Add 'email' to the requested OIDC scopes (Kavita's DefaultScopes include it — confirm your config didn't override).
- Ensure the user has an email address set in the identity provider's profile.
- Map the IdP's email claim to ClaimTypes.Email if it uses a custom name.
- Decode the IdToken to confirm the email claim is present and non-empty.
Defensive patterns
Strategy: validation
Validate before calling
var email = principal.FindFirstValue(ClaimTypes.Email);
if (string.IsNullOrEmpty(email))
return Challenge("OIDC token is missing the email claim."); Type guard
bool HasOidcEmail(ClaimsPrincipal p) =>
!string.IsNullOrWhiteSpace(p.FindFirstValue(ClaimTypes.Email)); Try / catch
try { var user = await oidcService.LoginOrCreate(Request, principal, ct); }
catch (KavitaException ex) when (ex.Message == "errors.oidc.missing-email")
{ return Challenge(); // request 'email' scope } Prevention
- Include 'email' (and 'profile') in requested OIDC scopes.
- Ensure the user has an email set in the IdP.
- Map custom email claims to ClaimTypes.Email.
When it happens
Trigger: OIDC login for a first-time user whose token has no email claim. The check fires only when no existing user matched the oidcId (new user path); returning users with valid oidcId bypass this entirely.
Common situations: The 'email' or 'profile' scope was not requested; provider doesn't expose email in tokens (some corporate IdPs); email claim mapped under a different name; user's profile in the IdP has no email set.
Related errors
- User is not authenticated
- errors.oidc.missing-external-id
- errors.oidc.no-account
- errors.oidc.email-not-verified
- errors.oidc.email-in-use
AI-assisted analysis of Kareadita/Kavita@9c3e540000 (2026-08-13).
Data as JSON: /api/errors/cc029964f532f899.
Report an issue: GitHub.