RocketChat/Rocket.Chat · error · Error

CustomOAuth: Failed to extract avatar url

Error message

CustomOAuth: Failed to extract avatar url

What it means

Legacy (deprecated, non-Passport) CustomOAuth class twin of the strategy error: getAvatarUrl() throws Error('CustomOAuth: Failed to extract avatar url', <inner message>) only when fromTemplate(this.avatarField, data) throws. A missing avatar value is not an error - it logs 'Avatar field not found in data' and returns undefined - so this indicates a broken avatarField template (invalid regex in a '{{/regex/::path}}' formula, or avatarField undefined with a direct call). It fails the login via normalizeIdentity.

Source

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

				return this.getName(data);
			}

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

	getAvatarUrl(data) {
		try {
			const value = fromTemplate(this.avatarField, data);

			if (!value) {
				logger.debug({ msg: 'Avatar field not found in data', avatarField: this.avatarField, data });
			}
			return value;
		} catch (error) {
			throw new Error('CustomOAuth: Failed to extract avatar url', error.message);
		}
	}

	getName(identity) {
		const name =
			identity.name ||
			identity.username ||
			identity.nickname ||
			identity.CharacterName ||
			identity.userName ||
			identity.preferred_username ||
			(identity.user && identity.user.name);
		return name;
	}

	addHookToProcessUser() {
		BeforeUpdateOrCreateUserFromExternalService.push(async (serviceName, serviceData /* , options*/) => {
			if (serviceName !== this.name) {

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Set Avatar Field to a plain dot path present in the identity payload, e.g. 'picture' or 'avatar_url'
  2. Compile-check any regex formula with new RegExp() before saving; it needs exactly one capture group
  3. Clear Avatar Field - extraction is optional and login succeeds without an avatar
  4. Check the CustomOAuth debug log for the printed payload to confirm the key name

Example fix

// before: Avatar Field = '{{/https:(.+)/::image}}' (broken regex)
// Error: CustomOAuth: Failed to extract avatar url ...

// after: Avatar Field = 'image_url'
Defensive patterns

Strategy: validation

Validate before calling

// verify the avatarField template against a captured payload
const capturedIdentity = JSON.parse(savedIdentityJson); // from CustomOAuth debug logs
if (avatarFieldSetting) {
  try {
    fromTemplate(avatarFieldSetting, capturedIdentity);
  } catch (e) {
    throw new Error(`Avatar Field 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 = customOAuth.getAvatarUrl(identity);
} catch (error) {
  logger.warn(`avatar extraction failed: ${error.message}`);
  identity.avatarUrl = undefined;
}

Prevention

When it happens

Trigger: avatarField configured with a formula whose regex fails new RegExp() during getIdentity; avatarField left undefined by configure() and getAvatarUrl invoked directly (getNestedValue throws on undefined.split).

Common situations: Older Rocket.Chat deployments still on the deprecated class; admin copies a regex mapping from docs and mistypes it; provider payload rename after upgrade.

Related errors


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