RocketChat/Rocket.Chat · warning · Meteor.Error
CustomOAuth: emailPath is required
Error message
CustomOAuth: emailPath is required
What it means
getEmailFromPath() refuses to run when the strategy instance has no emailPath configured. In the current code normalizeIdentity() only invokes it under 'if (!identity.email && this.emailPath)', so a live hit means the method was called directly (subclass, fork, or an older unguarded call path) on an instance constructed without the emailPath option.
Source
Thrown at apps/meteor/server/lib/auth-providers/custom-oauth/custom_oauth_server.js:278
identity.email = await this.getEmailFromPath(accessToken);
}
if (this.avatarField) {
identity.avatarUrl = this.getAvatarUrl(identity);
}
if (this.nameField) {
identity.name = this.getCustomName(identity);
} else {
identity.name = this.getName(identity);
}
return renameInvalidProperties(identity);
}
async getEmailFromPath(accessToken) {
if (!this.emailPath) {
throw new Meteor.Error('CustomOAuth: emailPath is required');
}
const params = {};
const headers = {
'User-Agent': this.userAgent,
'Accept': 'application/json',
};
if (this.identityTokenSentVia === 'header') {
headers.Authorization = `Bearer ${accessToken}`;
} else {
params[this.accessTokenParam] = accessToken;
}
try {
// SECURITY: URL can only be configured by users with enough privileges. It's ok to disable this check here.
const request = await fetch(`${this.emailPath}`, { method: 'GET', headers, params, ignoreSsrfValidation: true });
View on GitHub (pinned to b2c16d5842)
Solutions
- Pass emailPath in the CustomOAuth options (relative paths are auto-prefixed with serverURL), e.g. emailPath: '/api/v3/user/emails'
- Prefer emailField mapping when the e-mail is already present in the identity payload - then emailPath is unnecessary
- Do not call getEmailFromPath directly; go through the normal login flow so the guard applies
Example fix
// before
new CustomOAuth('gitea', { serverURL, tokenPath, identityPath });
// later: await strategy.getEmailFromPath(token) -> throws 'CustomOAuth: emailPath is required'
// after
new CustomOAuth('gitea', { serverURL, tokenPath, identityPath, emailPath: '/user/emails' }); Defensive patterns
Strategy: validation
Validate before calling
const hasEmailPath = (strategy: CustomOAuth): boolean =>
typeof strategy.emailPath === 'string' && strategy.emailPath.length > 0;
if (!hasEmailPath(strategy)) {
throw new Error('emailPath option is required before fetching e-mails from the provider');
} Try / catch
try {
email = await strategy.getEmailFromPath(accessToken);
} catch (error) {
if (/emailPath is required/.test(error.message)) {
email = identity.email; // fall back to whatever the identity payload already carries
} else {
throw error;
}
} Prevention
- Configure emailPath whenever the provider omits e-mail from the identity endpoint
- Prefer emailField over emailPath when possible - one less HTTP round trip and failure mode
- Never call getEmailFromPath outside the normalized login flow
When it happens
Trigger: Calling strategy.getEmailFromPath(accessToken) directly without having passed emailPath in the constructor options; running code from an older Rocket.Chat branch where normalizeIdentity called getEmailFromPath whenever identity.email was missing, regardless of emailPath.
Common situations: Custom forks or Apps that subclass the deprecated CustomOAuth class to fetch e-mails; upgrades where a private branch kept the old unguarded call; unit tests exercising getEmailFromPath in isolation.
Related errors
- field_not_found
- CustomOAuth: Failed to extract email
- CustomOAuth: Failed to extract username
- CustomOAuth: Failed to extract email
- CustomOAuth: Failed to extract custom name
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/d82bc7830cf53d0a.
Report an issue: GitHub.