RocketChat/Rocket.Chat · error · Error

error-invalid-room

Error message

error-invalid-room

What it means

Thrown by POST /api/v1/livechat/room.forward when LivechatRooms.findOneById(roomId) returns null OR the found room's type is not 'l'. Both 'no such room' and 'room exists but is not an omnichannel room' collapse into this single error before any transfer logic runs.

Solutions

  1. Confirm the rid refers to an omnichannel room (e.g. GET livechat/rooms, or check room.t === 'l' in whatever source produced it)
  2. Re-fetch the room list and use a current _id
  3. Check server logs for the exact roomId received to spot truncation/encoding issues

Example fix

// before
forward({ roomId: channel._id, ... }); // channel rid, t !== 'l'

// after
if (room.t !== 'l') throw new Error('cannot forward a non-omnichannel room');
forward({ roomId: room._id, ... });
Defensive patterns

Strategy: type-guard

Validate before calling

const rooms = await (await fetch(`${url}/api/v1/livechat/rooms`, { headers: authHeaders })).json();
const target = rooms.rooms?.find((r) => r._id === roomId && r.t === 'l');
if (!target) throw new Error('cannot forward: not an omnichannel room');

Type guard

function isLivechatRoomId(room) {
  return Boolean(room) && room.t === 'l' && typeof room._id === 'string';
}

Try / catch

try { await forward(roomId, payload); } catch (e) { if (e.message === 'error-invalid-room') { await refreshRoomCache(); return; } throw e; }

Prevention

When it happens

Trigger: Authenticated call (requires view-l-room + transfer-livechat-guest permissions) with a roomId that does not exist, a roomId of a regular channel/group/DM, or a truncated/malformed ObjectId.

Common situations: Integration forwards a rid taken from a normal chat payload instead of an omnichannel room; room deleted between listing and forwarding; copy/paste truncation of the _id.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: 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 b2c16d5842)