RocketChat/Rocket.Chat · error · Error

room-closed

Error message

room-closed

What it means

Thrown by POST /livechat/message (message.ts:41-43) when the room exists and belongs to the visitor but room.open is false — the livechat conversation has been closed (by agent, visitor, inactivity auto-close, etc.). Returns HTTP 400 { success:false, error:'room-closed' }.

Source

Thrown at apps/meteor/server/api/v1/omnichannel/message.ts:42

API.v1.addRoute(
	'livechat/message',
	{ validateParams: isPOSTLivechatMessageParams },
	{
		async post() {
			const { token, rid, agent, msg } = this.bodyParams;

			const guest = await findGuest(token);
			if (!guest) {
				throw new Error('invalid-token');
			}

			const room = await findRoom(token, rid);
			if (!room) {
				throw new Error('invalid-room');
			}

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

			if (
				settings.get('Livechat_enable_message_character_limit') &&
				msg.length > parseInt(settings.get('Livechat_message_character_limit'))
			) {
				throw new Error('message-length-exceeds-character-limit');
			}

			const _id = this.bodyParams._id || Random.id();

			const messageToSend = {
				guest,
				message: {
					_id,
					rid,
					msg,
					token,

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Start a new livechat session / reopen the chat to obtain a new open room before sending.
  2. Inspect room.open before posting; if closed, prompt the user to begin a new conversation.
  3. If reopening is supported in your flow, re-open the existing room and retry.

Example fix

// before
POST /livechat/message { token, rid, msg } // room-closed

// after
const room = await findRoom(token, rid);
if (room && !room.open) { /* start new conversation / reopen chat */ }
POST /livechat/message { token, rid, msg }
Defensive patterns

Strategy: validation

Validate before calling

const room = await findRoom(token, rid);
if (room && !room.open) {
  // start a new conversation / reopen, then retry
  throw new Error('room is closed');
}
// safe to POST /livechat/message

Type guard

const isRoomOpen = (room: IOmnichannelRoom | null): room is IOmnichannelRoom =>
  !!room && room.open === true;

Try / catch

try { await sendMessage({ token, rid, msg }); }
catch (e) { if (e instanceof Error && e.message === 'room-closed') { /* prompt new conversation */ } else throw e; }

Prevention

When it happens

Trigger: Sending a message to a livechat room whose `open` flag is false.

Common situations: Chat ended by agent or visitor; auto-close after inactivity timeout; attempting to reply after the session was closed.

Related errors


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