RocketChat/Rocket.Chat · error · Meteor.Error

field_not_found

field_not_found

Error message

Username field "${this.usernameField}" not found in data

What it means

Thrown by CustomOAuthStrategy.getUsername when fromTemplate(this.usernameField, data) resolves to a falsy value — the configured username field/template does not exist in the identity payload returned by the OAuth provider's identity endpoint. It is a Meteor.Error('field_not_found') that is immediately re-wrapped (see error 636). The usernameField template may be a dot-path ('user.login') or a {{regex::path}} formula evaluated against the provider's response body.

Source

Thrown at apps/meteor/server/lib/auth-providers/custom-oauth/customOAuth.ts:135

		if (config.addAutopublishFields && typeof config.addAutopublishFields === 'object') {
			Accounts.addAutopublishFields(config.addAutopublishFields);
		}

		this.name = name;
		this.options = options;
		this.config = config;

		this.addHookToProcessUser();
	}

	getUsername(data: Record<string, any>) {
		try {
			const value = fromTemplate(this.usernameField, data);

			if (!value) {
				logger.debug({ msg: 'Username field not found in data', usernameField: this.usernameField, data });
				throw new Meteor.Error('field_not_found', `Username field "${this.usernameField}" not found in data`);
			}

			return value as string;
		} catch (error) {
			throw new Error('CustomOAuth: Failed to extract username', { cause: error });
		}
	}

	getEmail(data: Record<string, any>) {
		try {
			const value = fromTemplate(this.emailField, data);

			if (!value) {
				logger.debug({ msg: 'Email field not found in data', emailField: this.emailField, data });
				throw new Meteor.Error('field_not_found', `Email field "${this.emailField}" not found in data`);
			}
			return value as string;
		} catch (error) {

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Inspect the actual identity payload (debug log 'Username field not found in data' includes the data) and correct usernameField to the real path (supports dot notation and {{regex::path}} templates)
  2. If the provider hides the claim, extend the requested scopes so the username claim is returned
  3. Alternatively clear usernameField so Rocket.Chat derives the username from other fields instead of hard-failing

Example fix

// before (provider returns { user: { login: 'jane' } })
usernameField: 'username'

// after
usernameField: 'user.login'
Defensive patterns

Strategy: validation

Validate before calling

import { fromTemplate } from './transform_helpers';

// verify the mapping against a captured sample of the IdP /me response
const sample = await fetchIdentityEndpointSample();
if (!fromTemplate('user.login', sample)) {
	throw new Error('usernameField does not resolve against provider payload');
}

Type guard

const resolvesIn = (template: string, data: Record<string, unknown>): boolean =>
	Boolean(fromTemplate(template, data));

Prevention

When it happens

Trigger: Custom OAuth login where usernameField is set (e.g., 'username') but the IdP's identity response uses a different shape ('login', 'preferred_username', nested 'user.login'); nested path wrong for providers like Keycloak/Nextcloud; {{regex}} formula whose capture group matches nothing so the result is undefined.

Common situations: Provider API version changed its /me response schema; field-mapping typo in the OAuth app config; scopes changed so claims disappeared; switching providers without updating field mappings.

Related errors


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