RocketChat/Rocket.Chat · warning · Meteor.Error
You_cant_leave_a_livechat_room_Please_use_the_close_button
Error message
You_cant_leave_a_livechat_room_Please_use_the_close_button
What it means
A beforeLeaveRoomCallback registered at Meteor.startup blocks the generic 'leave room' action for omnichannel rooms: if isOmnichannelRoom(room) is true it throws a Meteor.Error whose message is the translated key 'You_cant_leave_a_livechat_room_Please_use_the_close_button' (translated into the user's language). Livechat rooms are closed, not left — leaving would corrupt the agent/visitor relationship model.
Source
Thrown at apps/meteor/server/lib/omnichannel/startup.ts:77
await ContactMerger.mergeFieldsIntoContact({
fields,
contact,
conflictHandlingMode: contact.unknown ? 'overwrite' : 'conflict',
});
}
return visitor;
});
Meteor.startup(async () => {
roomCoordinator.setRoomFind('l', async (id) => maybeMigrateLivechatRoom(await LivechatRooms.findOneById(id)));
beforeLeaveRoomCallback.add(
(user, room) => {
if (!isOmnichannelRoom(room)) {
return;
}
throw new Meteor.Error(
i18n.t('You_cant_leave_a_livechat_room_Please_use_the_close_button', {
lng: user.language || settings.get('Language') || 'en',
}),
);
},
callbacks.priority.LOW,
'cant-leave-omnichannel-room',
);
callbacks.add(
'beforeJoinRoom',
async (user, room) => {
if (isOmnichannelRoom(room) && !(await hasPermissionAsync(user, 'view-l-room'))) {
throw new Meteor.Error('error-user-is-not-agent', 'User is not an Omnichannel Agent', {
method: 'beforeJoinRoom',
});
}
View on GitHub (pinned to b2c16d5842)
Solutions
- For livechat rooms use the omnichannel close/return flows (the close button, or the room close APIs) instead of leaveRoom
- Guard client-side: hide/disable the leave action when room.t === 'l'
- If an agent should no longer handle the chat, close the conversation or transfer it — never leave
- Catch this specific translated error in generic leave UIs and show the proper close affordance
Example fix
// before
Meteor.call('leaveRoom', room._id); // throws for livechat rooms
// after
if (room.t === 'l') {
// omnichannel rooms are closed, not left
Meteor.call('livechat:closeRoom', room._id);
} else {
Meteor.call('leaveRoom', room._id);
} Defensive patterns
Strategy: validation
Validate before calling
// generic leave flow: branch on room type before calling leaveRoom
function canLeaveRoom(room: { t: string }): boolean {
return room.t !== 'l'; // omnichannel rooms cannot be left, only closed
} Type guard
function isOmnichannelRoom(v: { t?: string } | null | undefined): v is { _id: string; t: 'l' } {
return v?.t === 'l';
} Try / catch
try {
await Meteor.callAsync('leaveRoom', rid);
} catch (err) {
if (err instanceof Meteor.Error && /livechat_room/i.test(err.reason ?? '')) {
// show 'use the close button' guidance instead of a generic error
} else {
throw err;
}
} Prevention
- Never wire the channel 'leave' action to livechat rooms — check room.t first
- Hide leave affordances in omnichannel context; offer close/transfer instead
- For apps-engine bots, use omnichannel-specific APIs rather than generic room membership calls
When it happens
Trigger: Any code path that ends in the 'leaveRoom' Meteor method/callback chain for a room with t: 'l' — e.g. a client calling leaveRoom on an omnichannel room, or a generic UI component reusing the channel-leave flow for livechat.
Common situations: Custom apps or UI components assuming all rooms support 'leave', users pressing a leave shortcut on a livechat conversation, or integrations calling Meteor.call('leaveRoom', rid) generically.
Related errors
- This_conversation_is_already_closed
- error-invalid-custom-field-value
- error-invalid-custom-field-value
- FileUpload_Error
- error-contact-not-found
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/686d68fb67f4b822.
Report an issue: GitHub.