RocketChat/Rocket.Chat · error · Error

CustomOAuth: Failed to extract email

Error message

CustomOAuth: Failed to extract email

What it means

getEmail()'s catch block flattens any inner failure - the field_not_found Meteor.Error, an invalid regex SyntaxError in the template, or a TypeError from a broken path - into Error('CustomOAuth: Failed to extract email', <inner message>), discarding the Meteor error code and payload details. It fires during normalizeIdentity, right after the identity endpoint responds, and aborts the whole OAuth login.

Source

Thrown at apps/meteor/server/lib/auth-providers/custom-oauth/custom_oauth_server.js:336

			if (!value) {
				throw new Meteor.Error('field_not_found', `Username field "${this.usernameField}" not found in data`, data);
			}
			return value;
		} catch (error) {
			throw new Error('CustomOAuth: Failed to extract username', error.message);
		}
	}

	getEmail(data) {
		try {
			const value = fromTemplate(this.emailField, data);

			if (!value) {
				throw new Meteor.Error('field_not_found', `Email field "${this.emailField}" not found in data`, data);
			}
			return value;
		} catch (error) {
			throw new Error('CustomOAuth: Failed to extract email', error.message);
		}
	}

	getCustomName(data) {
		try {
			const value = fromTemplate(this.nameField, data);

			if (!value) {
				return this.getName(data);
			}

			return value;
		} catch (error) {
			throw new Error('CustomOAuth: Failed to extract custom name', error.message);
		}
	}

	getAvatarUrl(data) {

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Enable CustomOAuth debug logging and read the 'Email field not found in data' record with the actual payload
  2. Fix emailField to an existing dot path, or clear it and use emailPath when the provider serves e-mails from a separate endpoint
  3. Add the 'email' scope to the service configuration so the claim is released
  4. Verify any regex formula compiles and matches before saving

Example fix

// before: Email Field = 'emailAddress'  (IdP releases 'email'; scope missing 'email' anyway)
// Error: CustomOAuth: Failed to extract email ...

// after: Email Field = 'email' and scope includes 'email'
Defensive patterns

Strategy: try-catch

Validate before calling

const assertEmailTemplateOk = (tpl: string, sample: Record<string, unknown>) => {
  try {
    if (!fromTemplate(tpl, sample)) throw new Error(`Email Field '${tpl}' does not resolve in the identity payload`);
  } catch (e) {
    throw new Error(`Email Field invalid: ${e.message}`);
  }
};

Try / catch

try {
  identity.email = strategy.getEmail(identity);
} catch (error) {
  if (/Failed to extract email/.test(error.message)) {
    return done(new Meteor.Error('oauth-email-mapping', 'E-mail mapping misconfigured. Contact admin.'));
  }
  throw error;
}

Prevention

When it happens

Trigger: emailField configured but its path does not resolve in the identity payload; emailField template contains an invalid '{{/regex/::path}}' expression; getEmail invoked directly on a strategy whose emailField is undefined so getNestedValue throws on undefined.split.

Common situations: E-mail claim withheld because the OAuth scope did not include 'email'; provider returns e-mail only via a separate endpoint; admin typo in the Email Field setting; IdP payload renamed after upgrade.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/c2e16053af6a8fc7. Report an issue: GitHub.