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
- Have the agent close or return ongoing chats until below the limit, then join
- Raise the agent chat limits in Administration > Omnichannel > Agents' capacity (global and/or per-department)
- 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
- Show live capacity counters in the agent desktop so takes/joins are pre-emptively blocked
- Align per-department limits with global limits to avoid surprise denials
- Re-check capacity immediately before automated joins, as counts change second-to-second
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
- error-max-number-simultaneous-chats-reached
- agent-not-found
- cannot-access-room
- department-not-found
- error-action-not-allowed
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)