RocketChat/Rocket.Chat · error · MeteorError

error-invalid-user

error-invalid-user

Error message

Invalid user

What it means

MeteorError('error-invalid-user', 'Invalid user') thrown by removeUserFromRolesAsync when the userId has no matching user document. The existence check runs before role validation, so a bad user id fails even if the roles are valid.

Source

Thrown at apps/meteor/server/lib/roles/removeUserFromRoles.ts:16

import { MeteorError } from '@rocket.chat/core-services';
import type { IRole, IUser, IRoom } from '@rocket.chat/core-typings';
import { Users, Subscriptions, Roles } from '@rocket.chat/models';

import { syncRoomRolePriorityForUserAndRoom } from './syncRoomRolePriority';
import { validateRoleList } from './validateRoleList';
import { notifyOnSubscriptionChangedByRoomIdAndUserId } from '../notifyListener';

export const removeUserFromRolesAsync = async (userId: IUser['_id'], roles: IRole['_id'][], scope?: IRoom['_id']): Promise<boolean> => {
	if (!userId || !roles) {
		return false;
	}

	const user = await Users.findOneById(userId, { projection: { _id: 1 } });
	if (!user) {
		throw new MeteorError('error-invalid-user', 'Invalid user');
	}

	if (!(await validateRoleList(roles))) {
		throw new MeteorError('error-invalid-role', 'Invalid role');
	}

	if (process.env.NODE_ENV === 'development' && (scope === 'Users' || scope === 'Subscriptions')) {
		throw new Error('Roles.removeUserRoles method received a role scope instead of a scope value.');
	}

	for await (const roleId of roles) {
		const role = await Roles.findOneById<Pick<IRole, '_id' | 'scope'>>(roleId, { projection: { scope: 1 } });
		if (!role) {
			continue;
		}

		if (role.scope === 'Subscriptions' && scope) {
			const removeRolesResponse = await Subscriptions.removeRolesByUserId(userId, [roleId], scope);

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Look the user up (Users.findOneById / users.info API) and drop or fix the work item.
  2. Treat removal for a deleted user as a skip, not a batch failure.
  3. Re-sync automation user lists to remove stale ids.

Example fix

// before
await removeUserFromRolesAsync(userId, ['bot']); // throws error-invalid-user

// after
const user = await Users.findOneById(userId, { projection: { _id: 1 } });
if (user) {
  await removeUserFromRolesAsync(userId, ['bot']);
}
Defensive patterns

Strategy: validation

Validate before calling

const user = await Users.findOneById(userId, { projection: { _id: 1 } });
if (!user) {
  // nothing to de-role: skip instead of failing the batch
} else {
  await removeUserFromRolesAsync(userId, roles, scope);
}

Try / catch

try {
  await removeUserFromRolesAsync(userId, roles, scope);
} catch (error: any) {
  if (error?.error === 'error-invalid-user') {
    // user deleted: drop the work item and continue
  }
}

Prevention

When it happens

Trigger: Removing roles from a user id that was deleted or never existed: stale job payloads, scripts, or retried API requests after user deletion.

Common situations: User deleted while a role-cleanup job was queued; imported data with dangling user references; retrying an old moderation action.

Related errors


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