RocketChat/Rocket.Chat · error · Error

error-invalid-room

error-invalid-room

Error message

error-invalid-room

What it means

Thrown in the POST handler of 'livechat/room.forward' (room.ts:294-297) when LivechatRooms.findOneById(this.bodyParams.roomId) returns null OR the found room's type field 't' is not 'l' (livechat). This is an authenticated endpoint requiring 'view-l-room' and 'transfer-livechat-guest' permissions. The room must exist and be an omnichannel room.

Source

Thrown at apps/meteor/server/api/v1/omnichannel/room.ts:296

			return API.v1.success({ rid, data: updateData });
		},
	},
);

API.v1.addRoute(
	'livechat/room.forward',
	{ authRequired: true, permissionsRequired: ['view-l-room', 'transfer-livechat-guest'], validateParams: isLiveChatRoomForwardProps },
	{
		async post() {
			const transferData = this.bodyParams as typeof this.bodyParams & {
				transferredBy: TransferByData;
				transferredTo?: { _id: string; username?: string; name?: string };
			};

			const room = await LivechatRooms.findOneById(this.bodyParams.roomId);
			if (room?.t !== 'l') {
				throw new Error('error-invalid-room');
			}

			if (!room.open) {
				throw new Error('This_conversation_is_already_closed');
			}

			if (!(await Omnichannel.isWithinMACLimit(room))) {
				throw new Error('error-mac-limit-reached');
			}

			const guest = await LivechatVisitors.findOneEnabledById(room.v?._id);
			if (!guest) {
				throw new Error('error-invalid-visitor');
			}

			transferData.transferredBy = normalizeTransferredByData(this.user, room);
			if (transferData.userId) {
				const userToTransfer = await Users.findOneById(transferData.userId);

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Verify the room exists and is a livechat room: db.livechat_rooms.findOne({_id: roomId}) — check that field 't' equals 'l'.
  2. Ensure the roomId was obtained from a livechat room listing or creation response.
  3. If the room was deleted, forwarding is not possible.

Example fix

// before
await api.post('/livechat/room.forward', { roomId: channelId });
// throws 'error-invalid-room' — channelId is a regular channel, not livechat

// after — use a valid livechat room ID
const livechatRoom = await LivechatRooms.findOne({t: 'l', _id: roomId});
if (!livechatRoom || livechatRoom.t !== 'l') {
  throw new Error('Room is not a livechat room');
}
await api.post('/livechat/room.forward', { roomId: livechatRoom._id });
Defensive patterns

Strategy: validation

Validate before calling

// Verify the room is a livechat room before forwarding
const room = await LivechatRooms.findOneById(roomId);
if (!room || room.t !== 'l') {
  throw new Error(`Room ${roomId} is not a livechat room or does not exist`);
}

Type guard

function isLivechatRoom(room: IOmnichannelRoom | null): room is IOmnichannelRoom {
  return room !== null && room.t === 'l';
}

Try / catch

try {
  await api.post('/livechat/room.forward', { roomId, ...transferData });
} catch (err) {
  if (err.message === 'error-invalid-room') {
    // verify room exists and is livechat type, then retry or inform user
    const room = await getRoomById(roomId);
    if (!room || room.t !== 'l') {
      throw new Error('Cannot forward: room is not a livechat room');
    }
  }
}

Prevention

When it happens

Trigger: Calling POST /api/v1/livechat/room.forward with a roomId that either doesn't exist in the database or exists but is not a livechat room (type !== 'l'). For example, forwarding a regular channel, direct message, or a non-existent room ID.

Common situations: roomId was mistyped or copied from a non-livechat room; the room was deleted before the forward request; attempting to forward a regular channel or DM (type 'c' or 'd' or 'p'); cross-environment ID mismatch.

Related errors


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