{"record":{"id":"55cd0803a4d3ed2d","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-room-55cd08","errorCode":"error-invalid-room","errorMessage":"Invalid room","messagePattern":"Invalid room","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/meteor-methods/rooms/getRoomRoles.ts","lineNumber":27,"sourceCode":"import { settings } from '../../settings';\n\ndeclare module '@rocket.chat/ddp-client' {\n\t// eslint-disable-next-line @typescript-eslint/naming-convention\n\tinterface ServerMethods {\n\t\tgetRoomRoles(rid: IRoom['_id']): RoomRoles[];\n\t}\n}\n\nexport const executeGetRoomRoles = async (rid: IRoom['_id'], fromUser?: IUser | null) => {\n\tcheck(rid, String);\n\n\tif (!fromUser && settings.get('Accounts_AllowAnonymousRead') === false) {\n\t\tthrow new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getRoomRoles' });\n\t}\n\n\tconst room = await Rooms.findOneById(rid);\n\tif (!room) {\n\t\tthrow new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'getRoomRoles' });\n\t}\n\n\tif (fromUser && !(await canAccessRoomAsync(room, fromUser))) {\n\t\tthrow new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getRoomRoles' });\n\t}\n\n\treturn getRoomRoles(rid);\n};\n","sourceCodeStart":9,"sourceCodeEnd":36,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/rooms/getRoomRoles.ts#L9-L36","documentation":"executeGetRoomRoles throws 'error-invalid-room' when Rooms.findOneById(rid) returns null: no room document exists with the supplied id. Unlike sibling methods that reuse 'error-not-allowed', this one names the problem accurately - the rid simply does not match any room.","triggerScenarios":"Calling getRoomRoles (or executeGetRoomRoles) with a deleted room id, a room id from another workspace, or a malformed value that still passes check(rid, String); races where roles are fetched right as a room is deleted.","commonSituations":"UI closing over a room while a parallel roles fetch is in flight; ids persisted from before a room deletion; copy-paste of rids between test and production databases.","solutions":["Re-verify the rid against the current rooms subscription or db.rooms before fetching roles","Handle 'error-invalid-room' by discarding cached state for that rid","Serialize room-close and roles-fetch logic so the fetch cannot outlive the room"],"exampleFix":"// before\nconst roles = await Meteor.callAsync('getRoomRoles', rid);\n\n// after - confirm the room is still open/live before fetching\nif (!RoomManager.getOpenedRoomByRid(rid)) return [];\nconst roles = await Meteor.callAsync('getRoomRoles', rid);","handlingStrategy":"validation","validationCode":"if (typeof rid !== 'string' || rid.length !== 17) throw new Error('malformed room id');\nif (!RoomManager.getOpenedRoomByRid(rid)) return []; // room no longer live\nconst roles = await Meteor.callAsync('getRoomRoles', rid);","typeGuard":null,"tryCatchPattern":"try {\n  const roles = await Meteor.callAsync('getRoomRoles', rid);\n} catch (e) {\n  if (e instanceof Meteor.Error && e.error === 'error-invalid-room') {\n    discardRoomState(rid); // room deleted - stop fetching roles for it\n  }\n}","preventionTips":["Cancel in-flight role fetches when the room view closes","Validate rids against the live rooms subscription before use","'error-invalid-room' here genuinely means not-found, unlike sibling methods"],"tags":["meteor","ddp","rooms","not-found"],"backgroundTag":"room-not-found","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}