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
- Ensure the room is loaded (open it, or fetch via /v1/rooms.info and hydrate the store) before generating the permalink.
- Handle the throw with a graceful fallback (e.g. link to the room once it loads).
- 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
- Hydrate Rooms.state for cross-room messages before building permalinks.
- Remember the room lookup has no server fallback, unlike the message lookup.
- In secondary surfaces (search, notifications), fetch room info alongside the message.
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)