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

  1. Ensure the rid passed belongs to a livechat room (created via the omnichannel/inquiry flow)
  2. Validate with a `Rooms.findOneById(rid, { projection: { t: 1 } })` style check before calling
  3. 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

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.