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
- Enable CustomOAuth debug logging and read the 'Email field not found in data' record with the actual payload
- Fix emailField to an existing dot path, or clear it and use emailPath when the provider serves e-mails from a separate endpoint
- Add the 'email' scope to the service configuration so the claim is released
- 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
- Request the 'email' scope up front
- Prefer emailPath when the IdP hides e-mail from the identity endpoint
- Compile-check regex formulas before saving them as field mappings
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
- CustomOAuth: Failed to extract username
- CustomOAuth: Failed to extract email
- CustomOAuth: Failed to extract username
- field_not_found
- CustomOAuth: Failed to extract custom name
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/c2e16053af6a8fc7.
Report an issue: GitHub.