RocketChat/Rocket.Chat · error · Error

room-not-found

Error message

room-not-found

What it means

After resolving the message, getPermaLink() throws 'room-not-found' when Rooms.state.get(msg.rid) returns undefined — the room containing the message is not present in the local Rooms store. Note the asymmetry: the message has a server fallback, the room lookup does not.

Solutions

  1. Ensure the room is loaded (open it, or fetch via /v1/rooms.info and hydrate the store) before generating the permalink.
  2. Handle the throw with a graceful fallback (e.g. link to the room once it loads).
  3. Await initial rooms sync before enabling copy-link in secondary surfaces.

Example fix

// before
const url = await getPermaLink(msgId); // throws room-not-found

// after
const msg = Messages.state.get(msgId) ?? (await sdk.rest.get('/v1/chat.getMessage', { msgId })).message;
if (!Rooms.state.get(msg.rid)) {
  await sdk.rest.get('/v1/rooms.info', { roomId: msg.rid }); // hydrate store first
}
const url = await getPermaLink(msgId);
Defensive patterns

Strategy: validation

Validate before calling

const msg = Messages.state.get(msgId) ?? (await sdk.rest.get('/v1/chat.getMessage', { msgId })).message;
if (!Rooms.state.get(msg.rid)) {
  await sdk.rest.get('/v1/rooms.info', { roomId: msg.rid }); // hydrate the store first
}
const url = await getPermaLink(msgId);

Try / catch

try {
  const url = await getPermaLink(msgId);
} catch (e) {
  if (e instanceof Error && e.message === 'room-not-found') {
    // room not cached: hydrate and retry once
    await sdk.rest.get('/v1/rooms.info', { roomId });
    return await getPermaLink(msgId);
  }
  throw e;
}

Prevention

When it happens

Trigger: Building a permalink for a message fetched from the server while its room was never loaded into Rooms.state (cross-room permalink, notification deep-link, search result from an unopened room), or when rooms have not finished syncing.

Common situations: Permalinks generated from search or notification contexts where only the message was fetched; startup races before the rooms subscription completes; room deleted server-side while the message row persists.

Related errors


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

Appendix: 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 2f18297792)