RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-user

error-invalid-user

Error message

User is not part of given room

What it means

Thrown by the 'authorization:addUserToRole' Meteor method when a role is assigned with a scope (a room _id) and the target user is not a member of that room. The server first resolves the role and user, then calls Roles.canAddUserToRole(user._id, role._id, scope), which returns false when the user has no subscription to the scoped room, so the assignment aborts with code 'error-invalid-user'. Room-scoped roles (moderator, leader, owner) are only valid for room members.

Source

Thrown at apps/meteor/server/meteor-methods/auth/addUserToRole.ts:53

			action: 'Assign_admin',
		});
	}

	const user = await Users.findOneByUsernameIgnoringCase(username, {
		projection: {
			_id: 1,
		},
	});

	if (!user?._id) {
		throw new Meteor.Error('error-user-not-found', 'User not found', {
			method: 'authorization:addUserToRole',
		});
	}

	// verify if user can be added to given scope
	if (scope && !(await Roles.canAddUserToRole(user._id, role._id, scope))) {
		throw new Meteor.Error('error-invalid-user', 'User is not part of given room', {
			method: 'authorization:addUserToRole',
		});
	}

	const add = await addUserRolesAsync(user._id, [role._id], scope);

	if (settings.get('UI_DisplayRoles')) {
		void api.broadcast('user.roleUpdate', {
			type: 'added',
			_id: role._id,
			u: {
				_id: user._id,
				username,
			},
			scope,
		});
	}

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Add the user to the room first (REST POST /api/v1/channels.addUser or addUserToRoom on the server), then retry the role assignment
  2. Verify the scope argument is the room's current _id and that the room still exists
  3. If a global role was intended, call the method without a scope argument

Example fix

// before — user has not joined the room
await Meteor.callAsync('authorization:addUserToRole', roleId, username, rid);

// after — ensure membership, then assign the scoped role
await fetch('/api/v1/channels.addUser', { method: 'POST', headers, body: JSON.stringify({ roomId: rid, username }) });
await Meteor.callAsync('authorization:addUserToRole', roleId, username, rid);
Defensive patterns

Strategy: validation

Validate before calling

// server-side pre-check mirroring the scoped-role rule
import { Subscriptions } from '@rocket.chat/models';

const canAssign = async (roomId: string | undefined, userId: string): Promise<boolean> => {
  if (!roomId) return true; // global role: no scope check
  const member = await Subscriptions.findOneByRoomIdAndUserId(roomId, userId, { projection: { _id: 1 } });
  return Boolean(member);
};

Type guard

const isMeteorErrorCode = (e: unknown, code: string): e is Meteor.Error => e instanceof Meteor.Error && e.error === code;

Try / catch

try {
  await Meteor.callAsync('authorization:addUserToRole', roleId, username, scope);
} catch (err) {
  if (isMeteorErrorCode(err, 'error-invalid-user')) {
    // user not in the scoped room: add membership, then retry
  }
}

Prevention

When it happens

Trigger: Calling addUserToRole(userId, roleId, username, scope) where scope is the _id of a room the target user has not joined; passing a stale rid of a deleted/recreated room; passing the wrong identifier (e.g. a team id) as the scope argument.

Common situations: An admin grants a room-scoped role from a user-management screen before adding the user to the room; automation scripts reuse an old rid captured earlier; the user left the room between page load and form submit; the room was deleted and recreated so the stored rid no longer matches a membership.

Related errors


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