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

  1. 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
  2. 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
  3. Temporarily clear the Avatar Field setting - avatar extraction is optional and login proceeds without it
  4. 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

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


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