RocketChat/Rocket.Chat · error

error-max-number-simultaneous-chats-reached

error-max-number-simultaneous-chats-reached

Error message

error-max-number-simultaneous-chats-reached

What it means

Thrown by the 'livechat.before-join-room' hook when an agent joining (taking) a livechat room would exceed their simultaneous-chat limits. It aggregates the agent's ongoing chats (total and per department via Users.getAgentAndAmountOngoingChats) and checks them with isAgentWithinChatLimits, which honours both the global 'Livechat maximum number of simultaneous chats per agent' and the per-department limits.

Solutions

  1. Have the agent close or return ongoing chats until below the limit, then join
  2. Raise the agent chat limits in Administration > Omnichannel > Agents' capacity (global and/or per-department)
  3. Route the room to another agent with spare capacity instead of forcing the join

Example fix

// before: joining and hitting error-max-number-simultaneous-chats-reached
await joinRoom(agentUser, rid);

// after: pre-check the identical limit helper used by the hook
const room = await Rooms.findOneById(rid);
const info = await Users.getAgentAndAmountOngoingChats(agentUser._id, room.departmentId);
const { chats = 0, chatsForDepartment = 0 } = info?.queueInfo ?? {};
if (!(await isAgentWithinChatLimits({
  agentId: agentUser._id,
  departmentId: room.departmentId,
  totalChats: chats,
  departmentChats: chatsForDepartment,
}))) {
  throw new Error('Agent at chat capacity; close a chat first');
}
await joinRoom(agentUser, rid);
Defensive patterns

Strategy: validation

Validate before calling

const agentCanJoin = async (agentId: string, departmentId?: string): Promise<boolean> => {
  const info = await Users.getAgentAndAmountOngoingChats(agentId, departmentId);
  if (!info) return false;
  const { chats = 0, chatsForDepartment = 0 } = info.queueInfo ?? {};
  return isAgentWithinChatLimits({ agentId, departmentId, totalChats: chats, departmentChats: chatsForDepartment });
};

Try / catch

try {
  await joinRoom(agentUser, rid);
} catch (err: any) {
  if (err?.message === 'error-max-number-simultaneous-chats-reached') {
    // surface 'close a chat first' or route to another agent; do not auto-retry
  }
  throw err;
}

Prevention

When it happens

Trigger: Agent closes/opens chats while at capacity and takes another room; department-specific limit lower than global; agent auto-assignment or manual 'take' racing after several simultaneous accepts.

Common situations: Limit settings lowered while agents were already overloaded; new department limit introduced; agents using keyboard/quick actions to take chats faster than rooms close.

Related errors


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

Appendix: source

Thrown at apps/meteor/ee/server/hooks/omnichannel/beforeJoinRoom.ts:30

		if (!settings.get('Livechat_waiting_queue')) {
			return user;
		}

		if (!room || !isOmnichannelRoom(room)) {
			return user;
		}
		const { departmentId } = room;
		const userSubs = await Users.getAgentAndAmountOngoingChats(user._id, departmentId);
		if (!userSubs) {
			return user;
		}
		const { queueInfo: { chats = 0, chatsForDepartment = 0 } = {} } = userSubs;

		if (await isAgentWithinChatLimits({ agentId: user._id, departmentId, totalChats: chats, departmentChats: chatsForDepartment })) {
			return user;
		}

		throw new Error('error-max-number-simultaneous-chats-reached');
	},
	callbacks.priority.MEDIUM,
	'livechat-before-join-room',
);

View on GitHub (pinned to b2c16d5842)