{"record":{"id":"200096ef72e84dca","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-user-200096","errorCode":"error-invalid-user","errorMessage":"User is not part of given room","messagePattern":"User is not part of given room","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/meteor-methods/auth/addUserToRole.ts","lineNumber":53,"sourceCode":"\t\t\taction: 'Assign_admin',\n\t\t});\n\t}\n\n\tconst user = await Users.findOneByUsernameIgnoringCase(username, {\n\t\tprojection: {\n\t\t\t_id: 1,\n\t\t},\n\t});\n\n\tif (!user?._id) {\n\t\tthrow new Meteor.Error('error-user-not-found', 'User not found', {\n\t\t\tmethod: 'authorization:addUserToRole',\n\t\t});\n\t}\n\n\t// verify if user can be added to given scope\n\tif (scope && !(await Roles.canAddUserToRole(user._id, role._id, scope))) {\n\t\tthrow new Meteor.Error('error-invalid-user', 'User is not part of given room', {\n\t\t\tmethod: 'authorization:addUserToRole',\n\t\t});\n\t}\n\n\tconst add = await addUserRolesAsync(user._id, [role._id], scope);\n\n\tif (settings.get('UI_DisplayRoles')) {\n\t\tvoid api.broadcast('user.roleUpdate', {\n\t\t\ttype: 'added',\n\t\t\t_id: role._id,\n\t\t\tu: {\n\t\t\t\t_id: user._id,\n\t\t\t\tusername,\n\t\t\t},\n\t\t\tscope,\n\t\t});\n\t}\n","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/auth/addUserToRole.ts#L35-L71","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before — user has not joined the room\nawait Meteor.callAsync('authorization:addUserToRole', roleId, username, rid);\n\n// after — ensure membership, then assign the scoped role\nawait fetch('/api/v1/channels.addUser', { method: 'POST', headers, body: JSON.stringify({ roomId: rid, username }) });\nawait Meteor.callAsync('authorization:addUserToRole', roleId, username, rid);","handlingStrategy":"validation","validationCode":"// server-side pre-check mirroring the scoped-role rule\nimport { Subscriptions } from '@rocket.chat/models';\n\nconst canAssign = async (roomId: string | undefined, userId: string): Promise<boolean> => {\n  if (!roomId) return true; // global role: no scope check\n  const member = await Subscriptions.findOneByRoomIdAndUserId(roomId, userId, { projection: { _id: 1 } });\n  return Boolean(member);\n};","typeGuard":"const isMeteorErrorCode = (e: unknown, code: string): e is Meteor.Error => e instanceof Meteor.Error && e.error === code;","tryCatchPattern":"try {\n  await Meteor.callAsync('authorization:addUserToRole', roleId, username, scope);\n} catch (err) {\n  if (isMeteorErrorCode(err, 'error-invalid-user')) {\n    // user not in the scoped room: add membership, then retry\n  }\n}","preventionTips":["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"],"tags":["authorization","roles","rooms","membership","meteor-methods"],"backgroundTag":"room-membership-required","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}