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

  1. Add email and profile scopes to the OAuth client in the provider
  2. Configure the correct email claim name in Immich OAuth settings
  3. Ensure the provider account has a verified email
  4. 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

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


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)