RocketChat/Rocket.Chat · error · Error

Room not found

Error message

Room not found

What it means

Thrown by getRoom, the strict getter that wraps findRoom. findRoom reads from the local Rooms state store (a client-side reactive cache keyed by room ID). If the room record is not present in that store, getRoom throws. This is a data layer function scoped to a specific rid (the chat context's room ID).

Source

Thrown at apps/meteor/client/lib/chats/data.ts:268

	const drafts = new Map<IMessage['_id'] | undefined, string>();

	const getDraft = async (mid: IMessage['_id'] | undefined): Promise<string | undefined> => drafts.get(mid);

	const discardDraft = async (mid: IMessage['_id'] | undefined): Promise<void> => {
		drafts.delete(mid);
	};

	const saveDraft = async (mid: IMessage['_id'] | undefined, draft: string): Promise<void> => {
		drafts.set(mid, draft);
	};

	const findRoom = async (): Promise<IRoom | undefined> => Rooms.state.get(rid);

	const getRoom = async (): Promise<IRoom> => {
		const room = await findRoom();

		if (!room) {
			throw new Error('Room not found');
		}

		return room;
	};

	const isSubscribedToRoom = async (): Promise<boolean> => !!Subscriptions.state.find((record) => record.rid === rid);

	const joinRoom = async (): Promise<void> => {
		await sdk.rest.post('/v1/rooms.join', { roomId: rid });
	};

	const findDiscussionByID = async (drid: IRoom['_id']): Promise<IRoom | undefined> =>
		Rooms.state.find((record) => Boolean(record._id === drid && record.prid));

	const getDiscussionByID = async (drid: IRoom['_id']): Promise<IRoom> => {
		const discussion = await findDiscussionByID(drid);

		if (!discussion) {

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Switch to findRoom() which returns undefined instead of throwing, and handle absence gracefully (show loading state, retry after sync).
  2. Ensure the Rooms store is hydrated before calling getRoom — wait for the subscription/rooms stream to complete initial load.
  3. Catch the error at the call site and trigger a room fetch from the server, then retry.
  4. Validate that the user is subscribed to the room before accessing it.

Example fix

// before
const room = await getRoom();
// after
const room = await findRoom();
if (!room) {
  await fetchRoomFromServer(rid);
  return;
}
Defensive patterns

Strategy: validation

Validate before calling

const room = await findRoom();
if (!room) {
  // wait for store hydration or fetch from server
  await fetchRoomData(rid);
  return;
}
// proceed with room data

Type guard

const roomExistsInStore = async (): Promise<boolean> => {
  return Boolean(await Rooms.state.get(rid));
};

Try / catch

try {
  const room = await getRoom();
} catch (e) {
  if (e instanceof Error && e.message === 'Room not found') {
    await refreshRoomStore();
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: The room data has not been loaded into the Rooms store yet (e.g., deep-linked directly to a room before subscription data arrives). The user is not a member of the room and the room metadata was never fetched. The room was deleted and its record removed from the store. Race condition: code calls getRoom before the initial subscriptions/rooms sync completes.

Common situations: Direct URL navigation to a room the user has not visited in this session. Room was archived/deleted while the user had the client open. Multi-tab scenario where another tab caused a store reset.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12). Data as JSON: /api/errors/5e9366e1f8921ff8. Report an issue: GitHub.