RocketChat/Rocket.Chat · error · Error

room-not-found

Error message

room-not-found

What it means

Thrown by getPermaLink after successfully finding the message but failing to find its parent room in the local Rooms store (Rooms.state.get(msg.rid)). This means the message was found (either in cache or via API) but the room metadata for the room it belongs to is not loaded in the client. getPermaLink needs room data to construct the room URL via roomCoordinator.

Source

Thrown at apps/meteor/client/lib/getPermaLink.ts:29

		return null;
	}
};

export const getPermaLink = async (msgId: string): Promise<string> => {
	if (!msgId) {
		throw new Error('invalid-parameter');
	}

	const { Messages, Rooms, Subscriptions } = await import('../stores');

	const msg = Messages.state.get(msgId) || (await getMessage(msgId));
	if (!msg) {
		throw new Error('message-not-found');
	}
	const roomData = Rooms.state.get(msg.rid);

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

	const subData = Subscriptions.state.find((record) => record.rid === roomData._id && record.u._id === getUserId());

	const { roomCoordinator } = await import('./rooms/roomCoordinator');

	const roomURL = roomCoordinator.getURL(roomData.t, { ...(subData || roomData), tab: '' });
	return `${roomURL}?msg=${msgId}`;
};

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Fetch the room data from the server before calling getPermaLink, or ensure Rooms store is hydrated.
  2. Catch the 'room-not-found' error and trigger a room fetch (e.g., /v1/rooms.info), then retry getPermaLink.
  3. Pre-load room metadata when the user navigates to a permalink from an external source.
  4. Show a 'room not available' message if the room no longer exists.

Example fix

// before
const link = await getPermaLink(msgId);
// after
try {
  const link = await getPermaLink(msgId);
} catch (e) {
  if (e instanceof Error && e.message === 'room-not-found') {
    await fetchRoomInfo(msg.rid);
    return getPermaLink(msgId); // retry
  }
  throw e;
}
Defensive patterns

Strategy: retry

Validate before calling

const msg = Messages.state.get(msgId);
if (msg && !Rooms.state.get(msg.rid)) {
  await fetchRoomInfo(msg.rid); // pre-load room data
}
const link = await getPermaLink(msgId);

Type guard

const roomDataAvailable = (rid: string): boolean =>
  Boolean(Rooms.state.get(rid));

Try / catch

try {
  const link = await getPermaLink(msgId);
} catch (e) {
  if (e instanceof Error && e.message === 'room-not-found') {
    await fetchRoomInfo(rid);
    return getPermaLink(msgId); // retry once
  }
  throw e;
}

Prevention

When it happens

Trigger: The message is accessible (found via cache or API) but the room metadata is not in the Rooms store. The room was deleted/archived and its metadata removed from the client. The user has access to the message (e.g., via a thread/discussion link) but the room data was not loaded in this session. Store hydration race condition.

Common situations: User clicks a permalink from an email/notification that deep-links to a message in a room they haven't opened this session. Room was archived after the message was sent. Fresh login where rooms haven't fully synced but messages are available via API.

Related errors


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