RocketChat/Rocket.Chat · error · Accounts.ConfigError

Service not configured

Error message

Service not configured

What it means

getAccessToken() looks up the service's entry in the ServiceConfiguration.configurations MongoDB collection before exchanging the OAuth authorization code; when no document exists for { service: this.name }, Meteor's Accounts.ConfigError is thrown, whose rendered message is 'Service <name> not configured'. Constructing the CustomOAuth class (driven by settings at startup) does not create that document - it is written only when an admin saves the service's credentials.

Source

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

		}

		if (!isAbsoluteURL(this.identityPath)) {
			this.identityPath = this.serverURL + this.identityPath;
		}

		if (this.emailPath && !isAbsoluteURL(this.emailPath)) {
			this.emailPath = this.serverURL + this.emailPath;
		}

		if (Match.test(options.addAutopublishFields, Object)) {
			Accounts.addAutopublishFields(options.addAutopublishFields);
		}
	}

	async getAccessToken(query) {
		const config = await ServiceConfiguration.configurations.findOneAsync({ service: this.name });
		if (!config) {
			throw new Accounts.ConfigError();
		}

		let response = undefined;

		const headers = {
			'Content-Type': 'application/x-www-form-urlencoded',
			'User-Agent': this.userAgent, // http://doc.gitlab.com/ce/api/users.html#Current-user
			'Accept': 'application/json',
		};
		const params = new URLSearchParams({
			code: query.code,
			redirect_uri: OAuth._redirectUri(this.name, config),
			grant_type: 'authorization_code',
			state: query.state,
		});

		// Only send clientID / secret once on header or payload.
		if (this.tokenSentVia === 'header') {

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Open Admin -> OAuth -> <custom service>, fill in Client id and Client Secret, and Save so the configuration document is (re)created
  2. Verify the document exists: db.ServiceConfiguration.configurations.findOne({ service: '<name>' }) in mongo
  3. Make sure the service is enabled (Accounts_OAuth_Custom-<name> = true) before users hit the login button
  4. Check for exact-name mismatches (case, whitespace) between the strategy name and the stored service field

Example fix

// mongo shell: confirm/seed the config the strategy expects
use rocketchat
db.ServiceConfiguration.configurations.insertOne({
  service: 'my-idp',
  clientId: '<client-id>',
  secret: '<client-secret>',
  loginStyle: 'popup'
})
Defensive patterns

Strategy: try-catch

Validate before calling

// server-side health check before exposing the login button
import { ServiceConfiguration } from 'meteor/service-configuration';

const isServiceConfigured = async (name: string): Promise<boolean> =>
  !!(await ServiceConfiguration.configurations.findOneAsync({ service: name }, { projection: { _id: 1 } }));

if (!(await isServiceConfigured('my-idp'))) renderLoginButtonDisabled('SSO not configured');

Try / catch

try {
  await customOAuth.getAccessToken(query);
} catch (error) {
  if (error instanceof Accounts.ConfigError) {
    throw new Meteor.Error('oauth-unconfigured', 'SSO service is not configured. Contact your administrator.');
  }
  throw error;
}

Prevention

When it happens

Trigger: The OAuth callback /_oauth/<name> is hit while Client id/Secret for the service were never saved; the ServiceConfiguration document was deleted directly in Mongo; the service was disabled and its configuration row removed; the database was restored/migrated without the ServiceConfiguration collection.

Common situations: Moving to a new instance with the same settings but a fresh mongo; test suites that instantiate CustomOAuth without seeding mongo; admin typed the settings but never pressed Save; exact-name mismatch (case/whitespace) between the strategy name and the stored service field.

Related errors


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