{"record":{"id":"8a6ba1594477112b","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-room-8a6ba1","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/messages/getUserMentionsByChannel.ts","lineNumber":32,"sourceCode":"\t}\n}\n\nexport const getUserMentionsByChannel = async (\n\tuserId: string,\n\troomId: string,\n\toptions: { limit?: number; skip?: number; sort?: { ts?: -1 | 1 } },\n) => {\n\tcheck(roomId, String);\n\n\tconst user = await Users.findOneById(userId);\n\tif (!user) {\n\t\tthrow new Meteor.Error('error-invalid-user', 'Invalid user');\n\t}\n\n\tconst room = await Rooms.findOneById(roomId);\n\n\tif (!room || !(await canAccessRoomAsync(room, user))) {\n\t\tthrow new Meteor.Error('error-invalid-room', 'Invalid room', {\n\t\t\tmethod: 'getUserMentionsByChannel',\n\t\t});\n\t}\n\n\treturn Messages.findVisibleByMentionAndRoomId(user.username, roomId, options).toArray();\n};\n\nMeteor.methods<ServerMethods>({\n\tasync getUserMentionsByChannel({ roomId, options }) {\n\t\tmethodDeprecationLogger.method('getUserMentionsByChannel', '9.0.0', '/v1/channels.getAllUserMentionsByChannel');\n\t\tconst uid = Meteor.userId();\n\n\t\tif (!uid) {\n\t\t\tthrow new Meteor.Error('error-invalid-user', 'Invalid user', {\n\t\t\t\tmethod: 'getUserMentionsByChannel',\n\t\t\t});\n\t\t}\n","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/messages/getUserMentionsByChannel.ts#L14-L50","documentation":"getUserMentionsByChannel throws error-invalid-room when Rooms.findOneById(roomId) finds nothing OR when canAccessRoomAsync(room, user) denies access — a single error covers both 'no such room' and 'no permission for this room'. The mentions query only runs for rooms the user can legitimately read.","triggerScenarios":"A roomId typo or deleted room; a private channel the user is not a member of; a DM the user is not part of; passing a room id obtained from a different workspace.","commonSituations":"Stale room ids in client state after room deletion; deep links referencing restricted channels; scripts exporting mentions that loop over every room id including restricted ones.","solutions":["Validate the room id and the caller's membership before calling","Clear cached references to deleted rooms","Catch error-invalid-room and skip the room instead of failing the whole export"],"exampleFix":"// before\nconst mentions = await getUserMentionsByChannel(uid, roomId, options);\n\n// after (client)\nconst sub = Subscriptions.findOne({ rid: roomId });\nif (!sub) {\n  // not a member or no such room locally — skip\n} else {\n  const mentions = await Meteor.callAsync('getUserMentionsByChannel', { roomId, options });\n}","handlingStrategy":"try-catch","validationCode":"const sub = Subscriptions.findOne({ rid: roomId });\nif (!sub) {\n  // no membership or unknown room — skip the mentions call\n}","typeGuard":null,"tryCatchPattern":"try {\n  const mentions = await Meteor.callAsync('getUserMentionsByChannel', { roomId, options });\n} catch (error) {\n  if (error instanceof Meteor.Error && error.error === 'error-invalid-room') {\n    return []; // room deleted or not accessible — treat as empty\n  }\n  throw error;\n}","preventionTips":["Validate room ids against the client's subscription cache before mention queries","Purge cached room references on deletion events","In export scripts, catch error-invalid-room per room and continue rather than aborting"],"tags":["authorization","mentions","room-access","meteor-method"],"backgroundTag":"room-access-denied","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}