RocketChat/Rocket.Chat · warning · Error

Room with id ${roomId} not found

Error message

Room with id ${roomId} not found

What it means

Thrown by the livechatEvent handler for IPostLivechatRoomSaved when the rooms converter's convertById returns null for the given roomId. The bridge cannot deliver the room-saved event to App listeners without a materialized room object, so it aborts. It signals the room record is missing at conversion time.

Source

Thrown at apps/meteor/app/apps/server/bridges/listeners.ts:477

			}

			case AppInterface.IPostLivechatGuestSaved: {
				const [visitorId] = args.payload;
				const visitor = await this.orch.getConverters().get('visitors').convertById(visitorId);

				if (!visitor) {
					throw new Error(`Visitor with id ${visitorId} not found`);
				}

				return this.orch.getManager().getListenerManager().executeListener(args.event, visitor);
			}

			case AppInterface.IPostLivechatRoomSaved: {
				const [roomId] = args.payload;
				const room = await this.orch.getConverters().get('rooms').convertById(roomId);

				if (!room) {
					throw new Error(`Room with id ${roomId} not found`);
				}

				return this.orch
					.getManager()
					.getListenerManager()
					.executeListener(args.event, room as IAppsLivechatRoom);
			}

			case AppInterface.IPostLivechatDepartmentDisabled: {
				const [departmentData] = args.payload;
				const department = await this.orch.getConverters().get('departments').convertDepartment(departmentData);

				if (!department) {
					throw new Error(`Department ${departmentData._id} not found`);
				}

				return this.orch.getManager().getListenerManager().executeListener(args.event, { department });
			}

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Confirm the room still exists in LivechatRooms when the after-save hook runs (check retention/prune policies and concurrent closeRoom calls).
  2. Ensure any code that manually emits IPostLivechatRoomSaved passes the rid of a committed room.
  3. Review omnichannel data-retention settings that may delete rooms faster than events are drained.
  4. Inspect server logs for the offending rid and query LivechatRooms directly to confirm the document is absent.
Defensive patterns

Strategy: try-catch

Validate before calling

const room = await LivechatRooms.findOneById(roomId);
if (!room) {
  return; // do not emit IPostLivechatRoomSaved
}
await emitEvent(AppInterface.IPostLivechatRoomSaved, { payload: [roomId] });

Type guard

const isPersistedRoomId = async (id: string): Promise<boolean> => {
  return Boolean(await LivechatRooms.findOneById(id, { projection: { _id: 1 } }));
};

Try / catch

try {
  await listenerManager.executeListener(args.event, room);
} catch (e) {
  this.orch.debugLog(`Skipping ${args.event} for room ${roomId}: ${(e as Error).message}`);
}

Prevention

When it happens

Trigger: Server emits IPostLivechatRoomSaved with a roomId; convertById resolves falsy because the LivechatRooms document was removed, the rid is malformed, or the room was archived/deleted between the save and the after-save hook execution.

Common situations: A room is closed and pruned immediately after being saved; an omni-core purge/retention policy removes the room; a custom flow dispatches IPostLivechatRoomSaved with a stale or fabricated rid; Mongo replication lag.

Related errors


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