{"record":{"id":"a197585fa9d3b698","repo":"RocketChat/Rocket.Chat","slug":"error-contact-has-open-rooms","errorCode":"error-contact-has-open-rooms","errorMessage":"error-contact-has-open-rooms","messagePattern":"error-contact-has-open-rooms","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/omnichannel/contacts/disableContact.ts","lineNumber":16,"sourceCode":"import type { ILivechatContact } from '@rocket.chat/core-typings';\nimport { LivechatContacts, LivechatRooms } from '@rocket.chat/models';\n\nimport { settings } from '../../../settings';\nimport { removeGuest } from '../guests';\n\nexport async function disableContactById(contactId: string): Promise<void> {\n\tconst contact = await LivechatContacts.findOneEnabledById<Pick<ILivechatContact, '_id' | 'channels'>>(contactId);\n\tif (!contact) {\n\t\tthrow new Error('error-contact-not-found');\n\t}\n\n\t// Checking if the contact has any open channel/room before removing its data.\n\tconst contactOpenRooms = await LivechatRooms.checkContactOpenRooms(contactId);\n\tif (contactOpenRooms && !settings.get<boolean>('Livechat_Allow_collect_and_store_HTTP_header_informations')) {\n\t\tthrow new Error('error-contact-has-open-rooms');\n\t}\n\n\t// Cleaning contact/visitor data;\n\tawait Promise.all(contact.channels.map((channel) => removeGuest({ _id: channel.visitor.visitorId })));\n\n\tawait LivechatContacts.disableByContactId(contactId);\n}\n","sourceCodeStart":1,"sourceCodeEnd":24,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/omnichannel/contacts/disableContact.ts#L1-L24","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import { LivechatRooms } from '@rocket.chat/models';\nimport { settings } from '../../../settings/server';\n\nconst hasOpen = await LivechatRooms.checkContactOpenRooms(contactId);\nif (hasOpen && !settings.get<boolean>('Livechat_Allow_collect_and_store_HTTP_header_informations')) {\n  // close the contact's open rooms first (or wait for auto-close) before disabling\n}","typeGuard":null,"tryCatchPattern":"try {\n  await disableContactById(contactId);\n} catch (err: any) {\n  if (err?.message === 'error-contact-has-open-rooms') {\n    await closeOpenRoomsForContact(contactId);\n    return disableContactById(contactId); // retry once the rooms are closed\n  }\n  throw err;\n}","preventionTips":["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"],"tags":["omnichannel","contacts","open-rooms","privacy","settings"],"backgroundTag":"resource-in-use","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}