RocketChat/Rocket.Chat · error · Meteor.Error

error-user-has-no-roles

error-user-has-no-roles

Error message

User has no roles

What it means

validateLoginAttempt throws error-user-has-no-roles when login.user.roles is missing or not an array. Rocket.Chat assumes every human user carries a roles array (at minimum 'user'); a document without it is treated as corrupt because all later authorization (hasPermission) would behave unpredictably.

Source

Thrown at apps/meteor/server/lib/auth/startup.js:445

	if (login.user.type === 'visitor') {
		return true;
	}

	if (login.user.type === 'app') {
		throw new Meteor.Error('error-app-user-is-not-allowed-to-login', 'App user is not allowed to login', {
			function: 'Accounts.validateLoginAttempt',
		});
	}

	if (!!login.user.active !== true) {
		throw new Meteor.Error('error-user-is-not-activated', 'User is not activated', {
			function: 'Accounts.validateLoginAttempt',
		});
	}

	if (!login.user.roles || !Array.isArray(login.user.roles)) {
		throw new Meteor.Error('error-user-has-no-roles', 'User has no roles', {
			function: 'Accounts.validateLoginAttempt',
		});
	}

	if (login.user.roles.includes('admin') === false && login.type === 'password' && settings.get('Accounts_EmailVerification') === true) {
		const validEmail = login.user.emails.filter((email) => email.verified === true);
		if (validEmail.length === 0) {
			throw new Meteor.Error('error-invalid-email', 'Invalid email __email__');
		}
	}

	login = await callbacks.run('onValidateLogin', login);

	await Users.updateLastLoginById(login.user._id);
	setImmediate(() => {
		return callbacks.run('afterValidateLogin', login);
	});

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Re-assign roles in Administration -> Users -> edit the user -> Roles (typically add 'user')
  2. Repair the document directly: db.users.updateOne({ _id: '<uid>' }, { $set: { roles: ['user'] } })
  3. Ensure migrations ran after upgrades (check the migrations collection and server startup logs)
  4. Always create users through Accounts.createUser or the admin APIs so defaults are applied

Example fix

// before (broken doc)
// db.users.findOne(uid) -> { _id: uid, username: 'bob', roles: null }

// after
// mongo shell:
db.users.updateOne({ _id: uid }, { $set: { roles: ['user'] } });
Defensive patterns

Strategy: type-guard

Validate before calling

const user = await Users.findOneById(uid);
if (!hasValidRoles(user)) {
  await Users.updateOne({ _id: uid }, { $set: { roles: ['user'] } }); // repair before login is attempted
}

Type guard

const hasValidRoles = (u: unknown): u is { roles: string[] } =>
  typeof u === 'object' && u !== null && Array.isArray((u as { roles?: unknown }).roles);

Try / catch

try {
  await loginWithPassword(user, password);
} catch (e) {
  if (e instanceof Meteor.Error && e.error === 'error-user-has-no-roles') {
    // data corruption: repair roles via admin/db, then retry once
  }
  throw e;
}

Prevention

When it happens

Trigger: Login as a user whose Mongo document lacks roles or stores it as a non-array (null, string, object) — after manual database surgery, a partial restore, a skipped migration, or custom code inserting users directly into the Users collection.

Common situations: Users inserted via mongoimport or scripts bypassing Accounts.createUser; database restored from a much older version without running migrations; a manual cleanup deleted the roles field instead of emptying it.

Related errors


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