RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-room

error-invalid-room

Error message

Invalid room

What it means

Thrown by executeArchiveRoom when Rooms.findOneById(rid) returns null: no room document matches the id passed to archiveRoom. The room record is required for the subsequent type-directive and permission checks, so a nonexistent room aborts immediately with error-invalid-room.

Source

Thrown at apps/meteor/server/meteor-methods/rooms/archiveRoom.ts:30

declare module '@rocket.chat/ddp-client' {
	// eslint-disable-next-line @typescript-eslint/naming-convention
	interface ServerMethods {
		archiveRoom(rid: string): Promise<void>;
	}
}

export const executeArchiveRoom = async (userId: string, rid: string) => {
	check(rid, String);

	const user = await Users.findOneById(userId, { projection: { username: 1, name: 1 } });
	if (!user || !isRegisterUser(user)) {
		throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'archiveRoom' });
	}

	const room = await Rooms.findOneById(rid);
	if (!room) {
		throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'archiveRoom' });
	}

	if (!(await roomCoordinator.getRoomDirectives(room.t).allowMemberAction(room, RoomMemberActions.ARCHIVE, userId))) {
		throw new Meteor.Error('error-direct-message-room', `rooms type: ${room.t} can not be archived`, { method: 'archiveRoom' });
	}

	if (!(await hasPermissionAsync(userId, 'archive-room', room._id))) {
		throw new Meteor.Error('error-not-authorized', 'Not authorized', { method: 'archiveRoom' });
	}

	return archiveRoom(rid, user);
};

Meteor.methods<ServerMethods>({
	async archiveRoom(rid) {
		methodDeprecationLogger.method('archiveRoom', '9.0.0', '/v1/channels.archive');
		const userId = Meteor.userId();
		if (!userId) {

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Confirm the room exists immediately before the call (e.g. GET /api/v1/rooms.info or the live local rooms cache).
  2. Refresh the client's room subscriptions so deleted rooms disappear from the UI.
  3. In automations, treat error-invalid-room as already-removed and skip it.

Example fix

// before
Meteor.call('archiveRoom', rid);

// after
const room = roomsCollection.findOne({ _id: rid }); // local, subscription-fed cache
if (!room) {
  removeRoomFromList(rid); // room vanished - sync UI instead of erroring
} else {
  Meteor.call('archiveRoom', rid);
}
Defensive patterns

Strategy: validation

Validate before calling

// client minimongo pre-check against the active rooms subscription
const room = roomsCollection.findOne({ _id: rid });
if (!room) {
  // rid no longer resolves - refresh subscriptions or drop the room from the UI
}

Try / catch

try {
  await Meteor.callAsync('archiveRoom', rid);
} catch (e) {
  if (e instanceof Meteor.Error && e.error === 'error-invalid-room') {
    // room already gone: sync local state and move on
    removeRoomFromList(rid);
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Meteor.call('archiveRoom', rid) where rid was deleted after the client loaded it (stale UI/subscription); passing a subscription _id or team id where the room _id is expected; scripts using exported room lists that are out of date.

Common situations: Archiving from a stale tab after another admin removed the room; rid typos or truncation in automation scripts; race where deletion completes between the client's check and the server's lookup.

Related errors


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