immich-app/immich · error · BadRequestException
OAuth profile does not have an email address
Error message
OAuth profile does not have an email address
What it means
Validation during OAuth callback user provisioning: after mapping the OIDC/OAuth profile, the service normalizes the email claim and needs it to look up or register the user. If the identity provider returned a profile without an email claim (and no email-scope consent), no account can be matched or created, so the sign-in is rejected with 400. Fires when the OAuth provider's scopes or the user's profile lack an email address.
Solutions
- Add email and profile scopes to the OAuth client in the provider
- Configure the correct email claim name in Immich OAuth settings
- Ensure the provider account has a verified email
- If email cannot be supplied, create users manually and disable auto-register
Example fix
// before // scopes: ['openid'] // after // scopes: ['openid', 'email', 'profile']
Defensive patterns
Strategy: validation
Validate before calling
if (!profile.email) throw new Error('OAuth provider must return an email claim for auto-registration'); Type guard
const hasEmail = (p: { email?: string | null }) => typeof p.email === 'string' && p.email.length > 0; Try / catch
try { await api.oauthCallback(dto, headers) } catch (e) { if (e.status === 400 && /does not have an email/.test(e.message)) { /* fix provider scopes/claims */ } throw e; } Prevention
- Always request email scope
- Test the provider's userinfo payload for the email claim
- Map claim names explicitly in settings
When it happens
Trigger: Auto-register enabled, no user matches profile.sub, and the ID token/userinfo lacks an email claim or it is empty.
Common situations: Provider client missing email/profile scopes; provider not exposing emails (some LDAP/GitHub setups); misconfigured email claim name in OAuth settings.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Invalid logout token: no claims found
- OAuth authentication failed
- Email is not available
- Email is not available
- Email is not available
AI-assisted analysis of immich-app/immich@f48d4b3321 (2026-09-15).
Data as JSON: /api/errors/2242882adb5de83e.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/auth.service.ts:345
const role = this.getRoleClaim(profile, roleClaim);
const isAdmin = role === 'admin';
if (user && role && isAdmin !== user.isAdmin) {
user = await this.userRepository.update(user.id, { isAdmin });
}
// register new user
if (!user) {
if (!autoRegister) {
this.logger.warn(
`Unable to register ${profile.sub}/${normalizedEmail || '(no email)'}. User does not exist and auto registering is disabled. To enable set OAuth Auto Register to true in admin settings.`,
);
throw new BadRequestException('OAuth authentication failed');
}
if (!normalizedEmail) {
throw new BadRequestException('OAuth profile does not have an email address');
}
this.logger.log(`Registering new user: ${profile.sub}/${normalizedEmail}`);
const storageLabel = this.getClaim(profile, {
key: storageLabelClaim,
default: '',
isValid: (value: unknown): value is string => typeof value === 'string',
});
const storageQuota = this.getClaim(profile, {
key: storageQuotaClaim,
default: defaultStorageQuota,
isValid: (value: unknown) => Number(value) >= 0,
});
user = await this.createUser({
name:
profile.name ||View on GitHub (pinned to f48d4b3321)