RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-room

error-invalid-room

Error message

Invalid room

What it means

unmuteUserInRoom loads the room with Rooms.findOneById(data.rid); a null result throws error-invalid-room before any moderation logic or permission checks on the target run.

Source

Thrown at apps/meteor/server/meteor-methods/rooms/unmuteUserInRoom.ts:29

declare module '@rocket.chat/ddp-client' {
	// eslint-disable-next-line @typescript-eslint/naming-convention
	interface ServerMethods {
		unmuteUserInRoom(data: { rid: IRoom['_id']; username: string }): boolean;
	}
}

export const unmuteUserInRoom = async (fromId: string, data: { rid: IRoom['_id']; username: string }): Promise<boolean> => {
	if (!fromId || !(await hasPermissionAsync(fromId, 'mute-user', data.rid))) {
		throw new Meteor.Error('error-not-allowed', 'Not allowed', {
			method: 'unmuteUserInRoom',
		});
	}

	const room = await Rooms.findOneById(data.rid);

	if (!room) {
		throw new Meteor.Error('error-invalid-room', 'Invalid room', {
			method: 'unmuteUserInRoom',
		});
	}

	if (!(await roomCoordinator.getRoomDirectives(room.t).allowMemberAction(room, RoomMemberActions.MUTE, fromId))) {
		throw new Meteor.Error('error-invalid-room-type', `${room.t} is not a valid room type`, {
			method: 'unmuteUserInRoom',
			type: room.t,
		});
	}

	const subscription = await Subscriptions.findOneByRoomIdAndUsername(data.rid, data.username, {
		projection: { _id: 1 },
	});

	if (!subscription) {
		throw new Meteor.Error('error-user-not-in-room', 'User is not in this room', {
			method: 'unmuteUserInRoom',

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Verify the room exists before invoking (REST rooms.info or the rooms collection on the server)
  2. Refresh room ids in long-lived integrations instead of caching them indefinitely
  3. Treat error-invalid-room from moderation methods as 'room gone' and clean up the UI/integration state

Example fix

// before
Meteor.call('unmuteUserInRoom', { rid, username }); // rid was deleted

// after
const room = await Rooms.findOneById(rid, { projection: { _id: 1 } });
if (!room) {
  // refresh state; do not call the method
} else {
  Meteor.call('unmuteUserInRoom', { rid: room._id, username });
}
Defensive patterns

Strategy: validation

Validate before calling

const room = await Rooms.findOneById(rid, { projection: { _id: 1 } });
if (!room) {
  // room no longer exists: refresh state instead of calling unmuteUserInRoom
}

Try / catch

try {
  await Meteor.callAsync('unmuteUserInRoom', { rid, username });
} catch (error) {
  if (error instanceof Meteor.Error && error.error === 'error-invalid-room') {
    // room gone: discard the moderation action and update UI state
  }
}

Prevention

When it happens

Trigger: Calling unmuteUserInRoom with the id of a deleted or nonexistent room, an id from another workspace, or a typo'd/malformed rid.

Common situations: Moderation UI acting on a room deleted moments earlier; stale room ids cached in integrations or bots; ids that lost characters when copied.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/4db250ae0d3c6c9c. Report an issue: GitHub.