RocketChat/Rocket.Chat · error · Error

This_conversation_is_already_closed

This_conversation_is_already_closed

Error message

This_conversation_is_already_closed

What it means

Thrown by the POST livechat/room.forward endpoint when the target Livechat room exists but has room.open === false, meaning the conversation was already closed. Rocket.Chat blocks transfers on closed rooms because the agent assignment and routing pipeline only operates on active omnichannel sessions. The guard fires before MAC, visitor, and transfer logic so a closed conversation fails fast.

Source

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

);

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);
				if (userToTransfer) {
					transferData.transferredTo = {
						_id: userToTransfer._id,
						username: userToTransfer.username,

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Before calling room.forward, fetch the room (GET livechat/rooms or livechat/room.open state) and verify room.open === true; abort the transfer UI if closed.
  2. Handle this specific error in the client by refreshing the room list and showing 'Conversation already closed' instead of retrying.
  3. If reopening is intended, call livechat/room.open first, then retry the forward.
  4. Audit close callbacks/webhooks firing earlier than expected (e.g. Livechat_room_inactivity_period, Livechat_room_close_on_agent_offline).

Example fix

// before
await POST('/api/v1/livechat/room.forward', { roomId, userId });

// after
const room = await GET('/api/v1/livechat/rooms', { query: JSON.stringify({ _id: roomId }) });
if (!room.open) {
  notifyUser('Conversation already closed');
  return;
}
await POST('/api/v1/livechat/room.forward', { roomId, userId });
Defensive patterns

Strategy: validation

Validate before calling

const room = await LivechatRooms.findOneById(roomId, { projection: { open: 1, t: 1 } });
if (!room || room.t !== 'l') throw new ClientError('invalid-room');
if (!room.open) throw new ClientError('room-closed');
// now safe to call POST livechat/room.forward

Type guard

const isForwardableRoom = (r: unknown): r is { open: true; t: 'l'; _id: string } =>
  !!r && typeof r === 'object' && (r as any).t === 'l' && (r as any).open === true && typeof (r as any)._id === 'string';

Try / catch

try {
  await POST('/api/v1/livechat/room.forward', { roomId, userId });
} catch (e) {
  if (e.message === 'This_conversation_is_already_closed') { refreshRoomList(); notifyClosed(); return; }
  throw e;
}

Prevention

When it happens

Trigger: POST /api/v1/v1/livechat/room.forward with a bodyParams.roomId that resolves to a Livechat room whose `open` field is false. Happens when the client holds a stale roomId after the room was closed via agent close, inactivity timeout, omnichannel callback, or a prior transfer that closed the source room.

Common situations: UI keeps a room list cached after an agent closes a chat and the user clicks 'transfer'; race between a close callback (e.g. webhook/timeout) and the transfer click; integration replaying a roomId from an earlier session; agent has the room open in a tab while another agent closes it.

Related errors


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