RocketChat/Rocket.Chat · error · Meteor.Error
invalid-room
invalid-room
Error message
invalid-room
What it means
Thrown by `getRoomMessages({ rid })` when the room cannot be found OR its `t` (type) is not `'l'` (livechat). Only omnichannel rooms are valid here: the query projects `{ t: 1 }` and any channel/private-group/direct room fails the `room?.t !== 'l'` check just as hard as a missing room.
Source
Thrown at apps/meteor/server/lib/omnichannel/getRoomMessages.ts:8
import type { MessageTypesValues, IRoom } from '@rocket.chat/core-typings';
import { Rooms, Messages } from '@rocket.chat/models';
import { Meteor } from 'meteor/meteor';
export async function getRoomMessages({ rid }: { rid: string }) {
const room = await Rooms.findOneById<Pick<IRoom, 't'>>(rid, { projection: { t: 1 } });
if (room?.t !== 'l') {
throw new Meteor.Error('invalid-room');
}
const ignoredMessageTypes: MessageTypesValues[] = [
'livechat_navigation_history',
'livechat_transcript_history',
'command',
'livechat-close',
'livechat-started',
'livechat_video_call',
];
return Messages.findVisibleByRoomIdNotContainingTypes(rid, ignoredMessageTypes, {
sort: { ts: 1 },
});
}
View on GitHub (pinned to b2c16d5842)
Solutions
- Ensure the rid passed belongs to a livechat room (created via the omnichannel/inquiry flow)
- Validate with a `Rooms.findOneById(rid, { projection: { t: 1 } })` style check before calling
- If the room was deleted, surface 'conversation no longer exists' instead of retrying
Example fix
// before
await getRoomMessages({ rid: generalChannelId });
// after
const room = await Rooms.findOneById<Pick<IRoom, 't'>>(rid, { projection: { t: 1 } });
if (room?.t !== 'l') throw new Error('Transcripts are only available for livechat rooms');
await getRoomMessages({ rid }); Defensive patterns
Strategy: type-guard
Validate before calling
const room = await Rooms.findOneById<Pick<IRoom, 't'>>(rid, { projection: { t: 1 } });
if (room?.t !== 'l') throw new Error('Not a livechat room');
await getRoomMessages({ rid }); Type guard
const isLivechatRoom = (room: Pick<IRoom, 't'> | null): room is Pick<IRoom, 't'> & { t: 'l' } =>
room?.t === 'l'; Try / catch
try {
await getRoomMessages({ rid });
} catch (e) {
if (isMeteorError(e, 'invalid-room')) {
// show 'conversation unavailable' — do not retry
}
} Prevention
- Only feed room ids originating from the omnichannel inquiry/room flow to livechat-only helpers
- Type-narrow rooms by t === 'l' before livechat-specific calls
- Handle deleted-room races with a terminal error state
When it happens
Trigger: Calling the transcript/message-history flow backed by this helper with a regular channel rid, a typo'd rid, or a room deleted between the client loading it and requesting its transcript.
Common situations: Widget or API code reusing a generic room id for a livechat-only endpoint; rooms removed by retention policies; confusion between channel names and livechat room ids.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/bbcd6b746dc1aee4.
Report an issue: GitHub.