RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-room

error-invalid-room

Error message

Invalid room

What it means

removeRoomModerator starts by loading the room with Rooms.findOneById(rid, ...) and throws error-invalid-room when no document matches. This fires before permission and user checks, so any nonexistent, deleted, or malformed room ID produces it. The second argument must be the room's _id, not its name.

Solutions

  1. Resolve the room first (client Rooms collection or GET /api/v1/rooms.info?roomId=) and pass the returned _id
  2. Refresh the room list in the client when the call fails to clear stale IDs
  3. Never build rid from a name; look up the _id explicitly

Example fix

// before
await Meteor.callAsync('removeRoomModerator', roomName, userId);

// after
const room = Rooms.findOne({ name: roomName });
if (!room) throw new Error('room gone');
await Meteor.callAsync('removeRoomModerator', room._id, userId);
Defensive patterns

Strategy: validation

Validate before calling

const room = Rooms.findOne({ _id: rid });
if (!room) {
  // refetch room list; the rid is stale or wrong
}

Type guard

const isExistingRoom = (rid: string | undefined): rid is string =>
  typeof rid === 'string' && rid.length > 0 && Rooms.findOne({ _id: rid }) != null;

Try / catch

try {
  await Meteor.callAsync('removeRoomModerator', rid, userId);
} catch (err) {
  if (err instanceof Meteor.Error && err.error === 'error-invalid-room') {
    // room gone: refresh UI state, do not retry the same rid
  }
}

Prevention

When it happens

Trigger: Passing a channel name or slug instead of the room _id; the room was deleted between the UI loading it and the method executing; a truncated or typo'd ObjectId string.

Common situations: Stale UI referencing a channel deleted by another admin; data copied between environments where room IDs differ; federation or app sync removing the room mid-flow.

Related errors


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

Appendix: source

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

import { methodDeprecationLogger } from '../../lib/deprecationWarningLogger';
import { notifyOnSubscriptionChangedById } from '../../lib/notifyListener';
import { syncRoomRolePriorityForUserAndRoom } from '../../lib/roles/syncRoomRolePriority';
import { settings } from '../../settings';

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

export const removeRoomModerator = async (fromUserId: IUser['_id'], rid: IRoom['_id'], userId: IUser['_id']): Promise<boolean> => {
	check(rid, String);
	check(userId, String);

	const room = await Rooms.findOneById(rid, { projection: { t: 1, federated: 1, federation: 1 } });
	if (!room) {
		throw new Meteor.Error('error-invalid-room', 'Invalid room', {
			method: 'removeRoomModerator',
		});
	}

	if (!(await hasPermissionAsync(fromUserId, 'set-moderator', rid)) && !isRoomFederated(room)) {
		throw new Meteor.Error('error-not-allowed', 'Not allowed', {
			method: 'removeRoomModerator',
		});
	}

	const user = await Users.findOneById(userId);

	if (!user?.username) {
		throw new Meteor.Error('error-invalid-user', 'Invalid user', {
			method: 'removeRoomModerator',
		});
	}

View on GitHub (pinned to b2c16d5842)