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

  1. Join the room (or get invited) before listing its members
  2. Hide the member-list UI for rooms the user has no subscription/access to — check the local subscription cache first
  3. 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

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.