RocketChat/Rocket.Chat · error · Error

invalid-room

Error message

invalid-room

What it means

Thrown by POST /livechat/message (message.ts:36-39) when findRoom(token, rid) returns null. findRoom (livechat.ts:59-74) looks the room up by id AND visitor token (findOneByIdAndVisitorToken), so null means either the room does not exist or it does not belong to the visitor owning `token`. Returns HTTP 400 { success:false, error:'invalid-room' }.

Source

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

import { settings } from '../../../settings';
import { getPaginationItems } from '../../lib/getPaginationItems';
import { isWidget } from '../../lib/isWidget';

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: {

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Ensure rid belongs to the visitor that owns `token` (use the rid returned by room creation).
  2. Pre-verify with findRoom(token, rid); if null, create/open a new room for the visitor.
  3. Confirm rid is the livechat room `_id`, not its name or a message id.

Example fix

// before
POST /livechat/message { token, rid: cachedRid, msg } // throws invalid-room after re-register

// after
const room = await findRoom(token, rid);
if (!room) { /* open a new room for this visitor first */ }
POST /livechat/message { token, rid: room._id, msg }
Defensive patterns

Strategy: validation

Validate before calling

const room = await findRoom(token, rid);
if (!room) {
  // open a new room for this visitor, then retry
  throw new Error('room not found for this visitor token');
}
// safe to POST /livechat/message

Type guard

const roomBelongsToVisitor = async (token: string, rid: string) =>
  !!(await LivechatRooms.findOneByIdAndVisitorToken(rid, token, { projection: { _id: 1 } }));

Try / catch

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

Prevention

When it happens

Trigger: POST /livechat/message with a rid that does not exist, belongs to a different visitor/token, or is the wrong kind of id.

Common situations: Reused rid after visitor re-registration (new token no longer matches the old room); typo; passing the room name or a messageId as rid.

Related errors


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