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
- Add the user to the room first (REST POST /api/v1/channels.addUser or addUserToRoom on the server), then retry the role assignment
- Verify the scope argument is the room's current _id and that the room still exists
- 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
- Add the user to the room before offering or submitting room-scoped role assignment
- Always pass the room's current _id as scope, re-reading it at submit time
- Hide scoped-role UI actions for users the current viewer knows are not members
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.