RocketChat/Rocket.Chat · error · Meteor.Error
not-authorized
not-authorized
Error message
Not Authorized
What it means
canAccessRoomAsync(room, { _id: userId }) returned false: the logged-in user cannot access this room. Private channels, teams, and DMs between other users require membership or elevated permissions, so non-members are rejected with not-authorized before any member data is queried.
Source
Thrown at apps/meteor/server/meteor-methods/users/getUsersOfRoom.ts:46
async getUsersOfRoom(rid, showAll, { limit, skip } = {}, filter) {
if (!rid) {
throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'getUsersOfRoom' });
}
check(rid, String);
const userId = Meteor.userId();
if (!userId) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getUsersOfRoom' });
}
const room = await Rooms.findOneById(rid, { projection: { ...roomAccessAttributes, broadcast: 1 } });
if (!room) {
throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'getUsersOfRoom' });
}
if (!(await canAccessRoomAsync(room, { _id: userId }))) {
throw new Meteor.Error('not-authorized', 'Not Authorized', { method: 'getUsersOfRoom' });
}
if (room.broadcast && !(await hasPermissionAsync(userId, 'view-broadcast-member-list', rid))) {
throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'getUsersOfRoom' });
}
// TODO this is currently counting deactivated users
const total = await Subscriptions.countByRoomIdWhenUsernameExists(rid);
const { cursor } = findUsersOfRoom({
rid,
status: !showAll ? { $ne: UserStatus.OFFLINE } : undefined,
limit,
skip,
filter,
});
return {View on GitHub (pinned to b2c16d5842)
Solutions
- Join the room (or get invited) before listing its members
- Hide the member-list UI for rooms the user has no subscription/access to — check the local subscription cache first
- On this error, refresh room subscriptions and route the user out of the inaccessible room
Example fix
// before
Meteor.callAsync('getUsersOfRoom', rid, showAll);
// after
const mySub = Subscriptions.findOne({ rid });
if (!mySub && !roomIsPublic(room)) {
// not a member of a private room — do not even ask the server
return;
}
await Meteor.callAsync('getUsersOfRoom', rid, showAll); Defensive patterns
Strategy: try-catch
Validate before calling
// heuristic: private rooms need a local subscription
const sub = Subscriptions.findOne({ rid });
if (!sub && room?.t !== 'c' && room?.t !== 'p') {
// no access — do not call
}
// note: for 'p' (private) rooms the server check is authoritative; keep the catch Try / catch
try {
await Meteor.callAsync('getUsersOfRoom', rid, showAll);
} catch (err) {
if ((err as { error?: string }).error === 'not-authorized') {
// user cannot access this room — route away, do not retry
}
} Prevention
- Only expose member lists for rooms present in the user's subscriptions
- Re-check access when reusing components across different rooms
- Refresh subscriptions on window focus to catch revoked memberships
When it happens
Trigger: Requesting members of a private room the user never joined, was removed from, or left; requesting a direct-message room the user is not a participant of.
Common situations: Deep links to private rooms the user lacks membership in; membership revoked mid-session while the member list was open; components reused across rooms without re-checking access.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/635875bfb334ce0e.
Report an issue: GitHub.