RocketChat/Rocket.Chat · warning · Error

Room ${roomData._id} is not a livechat room

Error message

Room ${roomData._id} is not a livechat room

What it means

Thrown by the default branch of livechatEvent after convertRoom succeeds but the resulting object fails the isLivechatRoom type guard. The bridge only dispatches livechat events for genuine omnichannel rooms; a room of another type (channel, direct, discussion) reaching this path is rejected. It protects App livechat listeners from receiving non-livechat rooms.

Source

Thrown at apps/meteor/app/apps/server/bridges/listeners.ts:517

				const department = await this.orch.getConverters().get('departments').convertDepartment(departmentData);

				if (!department) {
					throw new Error(`Department ${departmentData._id} not found`);
				}

				return this.orch.getManager().getListenerManager().executeListener(args.event, { department });
			}

			default:
				const [roomData] = args.payload;
				const room = await this.orch.getConverters().get('rooms').convertRoom(roomData);

				if (!room) {
					throw new Error(`Room ${roomData._id} not found`);
				}

				if (!isLivechatRoom(room)) {
					throw new Error(`Room ${roomData._id} is not a livechat room`);
				}

				return this.orch.getManager().getListenerManager().executeListener(args.event, room);
		}
	}

	async userEvent(args: HandleUserEvent): Promise<unknown> {
		switch (args.event) {
			case AppInterface.IPostUserLoggedIn:
			case AppInterface.IPostUserLoggedOut: {
				const [loggedInUser] = args.payload;
				const context = this.orch.getConverters().get('users').convertToApp(loggedInUser);
				return this.orch.getManager().getListenerManager().executeListener(args.event, context);
			}
			case AppInterface.IPostUserStatusChanged: {
				const [statusData] = args.payload;
				const { currentStatus, previousStatus } = statusData;
				const context = {

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Confirm the event payload references an omnichannel room (LivechatRooms, t === 'l').
  2. If the room was changed from livechat to another type, stop dispatching livechat events for it.
  3. Repair corrupted room documents whose t field is missing or invalid.
  4. Audit custom code that emits livechat events to ensure it only does so for livechat rooms.
Defensive patterns

Strategy: type-guard

Validate before calling

import { isLivechatRoom } from '<livechat room guard module>';

const room = await LivechatRooms.findOneById(roomData._id);
if (!room || !isLivechatRoom(room)) {
  // do not dispatch a livechat event for a non-livechat room
  return;
}
await emitEvent(args.event, { payload: [roomData] });

Type guard

const isLivechatRoomByType = (room: { t?: string } | null): room is { t: 'l' } =>
  room?.t === 'l';

Try / catch

try {
  if (!isLivechatRoom(room)) {
    this.orch.debugLog(`Room ${roomData._id} is not livechat; skipping ${args.event}`);
    return;
  }
  await listenerManager.executeListener(args.event, room);
} catch (e) {
  this.orch.debugLog(`Skipping ${args.event}: ${(e as Error).message}`);
}

Prevention

When it happens

Trigger: The default branch converts a room successfully, but isLivechatRoom(room) returns false, e.g. a non-omnichannel room (t:'c' | 'd' | 'p') was passed as the payload of a livechat-branded event, or a room's t field is missing/changed.

Common situations: A custom integration fires a livechat event with a regular room id; a room was migrated/converted away from livechat type; corrupted room data with a missing or wrong t field; an App that mishandles event routing.

Related errors


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