RocketChat/Rocket.Chat · error · Error
error-contact-has-open-rooms
error-contact-has-open-rooms
Error message
error-contact-has-open-rooms
What it means
Before wiping a contact's data, disableContactById checks for open rooms via LivechatRooms.checkContactOpenRooms; if any exist and the setting 'Livechat_Allow_collect_and_store_HTTP_header_informations' is false, it throws Error('error-contact-has-open-rooms'). That historically unrelated setting doubles as the override switch that allows disabling a contact even while it has open conversations.
Source
Thrown at apps/meteor/server/lib/omnichannel/contacts/disableContact.ts:16
import type { ILivechatContact } from '@rocket.chat/core-typings';
import { LivechatContacts, LivechatRooms } from '@rocket.chat/models';
import { settings } from '../../../settings';
import { removeGuest } from '../guests';
export async function disableContactById(contactId: string): Promise<void> {
const contact = await LivechatContacts.findOneEnabledById<Pick<ILivechatContact, '_id' | 'channels'>>(contactId);
if (!contact) {
throw new Error('error-contact-not-found');
}
// Checking if the contact has any open channel/room before removing its data.
const contactOpenRooms = await LivechatRooms.checkContactOpenRooms(contactId);
if (contactOpenRooms && !settings.get<boolean>('Livechat_Allow_collect_and_store_HTTP_header_informations')) {
throw new Error('error-contact-has-open-rooms');
}
// Cleaning contact/visitor data;
await Promise.all(contact.channels.map((channel) => removeGuest({ _id: channel.visitor.visitorId })));
await LivechatContacts.disableByContactId(contactId);
}
View on GitHub (pinned to b2c16d5842)
Solutions
- Close (or wait for auto-close of) all open rooms on the contact's channels, then retry the disable
- Enable 'Livechat_Allow_collect_and_store_HTTP_header_informations' to permit disabling contacts with open rooms (force behavior)
- Tighten omnichannel inactivity auto-close so stale open rooms stop blocking contact deletions
Defensive patterns
Strategy: validation
Validate before calling
import { LivechatRooms } from '@rocket.chat/models';
import { settings } from '../../../settings/server';
const hasOpen = await LivechatRooms.checkContactOpenRooms(contactId);
if (hasOpen && !settings.get<boolean>('Livechat_Allow_collect_and_store_HTTP_header_informations')) {
// close the contact's open rooms first (or wait for auto-close) before disabling
} Try / catch
try {
await disableContactById(contactId);
} catch (err: any) {
if (err?.message === 'error-contact-has-open-rooms') {
await closeOpenRoomsForContact(contactId);
return disableContactById(contactId); // retry once the rooms are closed
}
throw err;
} Prevention
- Close a contact's open chats before running privacy/erasure jobs
- Enable the HTTP-header setting when contact removal must proceed despite open rooms
- Tune inactivity auto-close so forgotten chats stop blocking erasure requests
When it happens
Trigger: Disabling a contact whose visitor still has an open livechat conversation on any of its channels, without the override setting enabled; the deletion guard fires before any guest data is removed.
Common situations: GDPR/privacy erasure jobs hitting contacts mid-conversation; abandoned-but-open chats that inactivity auto-close never expired; admins unaware that the HTTP-header setting acts as the force flag here.
Related errors
- error-contact-not-found
- error-action-not-allowed
- error-visitor-not-found
- error-cannot-place-chat-on-hold
- error-invalid-contact
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/a197585fa9d3b698.
Report an issue: GitHub.