RocketChat/Rocket.Chat · error · Error
CustomOAuth: Failed to extract avatar url
Error message
CustomOAuth: Failed to extract avatar url
What it means
Thrown by CustomOAuthStrategy.getAvatarUrl (the Passport-based custom OAuth strategy) when fromTemplate(this.avatarField, data) throws while reading the avatar URL out of the provider's identity payload. A simply missing avatar value does NOT raise this - that case only logs 'Avatar field not found in data' and returns undefined - so hitting this error means the avatarField template itself is broken, most often an invalid regular expression inside a '{{/regex/::path}}' formula. The error propagates through normalizeIdentity/userProfile and fails the entire OAuth login.
Source
Thrown at apps/meteor/server/lib/auth-providers/custom-oauth/customOAuth.ts:181
return this.getName(data);
}
return value as string;
} catch (error) {
throw new Error('CustomOAuth: Failed to extract custom name', { cause: error });
}
}
getAvatarUrl(data: Record<string, any>) {
try {
const value = fromTemplate(this.avatarField, data);
if (!value) {
logger.debug({ msg: 'Avatar field not found in data', avatarField: this.avatarField, data });
}
return value as string;
} catch (error) {
throw new Error('CustomOAuth: Failed to extract avatar url', { cause: error });
}
}
getName(identity: Record<string, any>): string {
const name = (identity.name ||
identity.username ||
identity.nickname ||
identity.CharacterName ||
identity.userName ||
identity.preferred_username ||
identity.user?.name) as string;
return name;
}
normalizeIdentity(identity: Record<string, any>) {
if (identity) {
for (const normalizer of Object.values(normalizers)) {
const result = normalizer(identity);View on GitHub (pinned to b2c16d5842)
Solutions
- Set Avatar Field (avatarField) to a plain dot path that exists in the identity payload, e.g. 'picture' or 'user.avatar_url', instead of a regex formula
- If you keep a '{{/regex/::path}}' formula, test the regex in isolation (new RegExp('<regex>')) and make sure it is valid and has exactly one capture group
- Temporarily clear the Avatar Field setting - avatar extraction is optional and login proceeds without it
- Enable debug logging for the CustomOAuth logger and inspect the 'Avatar field not found in data' record to see the real payload shape
Example fix
// before (Admin -> OAuth -> <custom service> -> Avatar Field)
{{/^(.+)@/::picture}} // regex is broken/unbalanced -> SyntaxError -> login fails
// after
picture // plain dot-path into the identity payload Defensive patterns
Strategy: validation
Validate before calling
// server-side: verify the configured template resolves against a sample payload before users log in
import { fromTemplate } from '../auth-providers/custom-oauth/transform_helpers';
const sampleIdentity = await fetchIdentityFromProviderOnce(); // GET identityPath with a test token
const tpl = settings.get('Accounts_OAuth_Custom-MyIdp_avatarField');
try {
const v = fromTemplate(tpl, sampleIdentity);
if (!v) console.warn('avatar template resolves empty; login still works');
} catch (e) {
throw new Error(`avatarField template is broken: ${e.message}`);
} Type guard
const isResolvableTemplate = (tpl: string, data: Record<string, unknown>): boolean => {
try {
return fromTemplate(tpl, data) != null;
} catch {
return false;
}
}; Try / catch
try {
identity.avatarUrl = strategy.getAvatarUrl(identity);
} catch (error) {
logger.warn(`avatar extraction failed for ${strategy.name}: ${error.message}`);
identity.avatarUrl = undefined; // avatar is optional; continue the login
} Prevention
- Prefer plain dot-path avatarField values over regex formulas
- Test every '{{/regex/::path}}' formula against a real identity payload before saving the OAuth config
- Keep avatarField empty when the provider has no avatar claim - extraction is skipped safely
- Re-check CustomOAuth debug logs after any provider payload change
When it happens
Trigger: A user completes the OAuth redirect to /_oauth/<name>, the strategy fetches the identity, and avatarField is configured with a template formula whose embedded regex fails new RegExp() (SyntaxError), e.g. avatarField: '{{/[a-z+/::image}}'. Also triggered by calling getAvatarUrl on an instance whose avatarField is undefined (getNestedValue then throws on undefined.split).
Common situations: Admin copies a mapping formula from a blog post and the regex never compiles; provider payload rename makes the path portion resolve against a non-object; switching IdPs and reusing the old Avatar Field value; typos in the regex literal form (unbalanced slashes, smart quotes).
Related errors
- CustomOAuth: Failed to extract avatar url
- CustomOAuth: Failed to extract custom name
- CustomOAuth: Failed to extract custom name
- field_not_found
- CustomOAuth: Failed to extract username
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/0b67c8922868dbf4.
Report an issue: GitHub.