{"record":{"id":"f92f99c07f3d15c8","repo":"RocketChat/Rocket.Chat","slug":"error-contact-not-found","errorCode":"error-contact-not-found","errorMessage":"error-contact-not-found","messagePattern":"error-contact-not-found","errorType":"exception","errorClass":"Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/ee/server/api/v1/omnichannel/lib/contacts.ts","lineNumber":12,"sourceCode":"import type { IUser, ILivechatContactVisitorAssociation } from '@rocket.chat/core-typings';\nimport { License } from '@rocket.chat/license';\nimport { LivechatContacts, LivechatRooms, LivechatVisitors } from '@rocket.chat/models';\n\nimport { i18n } from '../../../../../../server/lib/i18n';\nimport { closeRoom } from '../../../../../../server/lib/omnichannel/closeRoom';\n\nexport async function changeContactBlockStatus({ block, visitor }: { visitor: ILivechatContactVisitorAssociation; block: boolean }) {\n\tconst result = await LivechatContacts.setChannelBlockStatus(visitor, block);\n\n\tif (!result.modifiedCount) {\n\t\tthrow new Error('error-contact-not-found');\n\t}\n}\n\nexport function ensureSingleContactLicense() {\n\tif (!License.hasModule('contact-id-verification')) {\n\t\tthrow new Error('error-action-not-allowed');\n\t}\n}\n\nexport async function closeBlockedRoom(association: ILivechatContactVisitorAssociation, user: IUser) {\n\tconst visitor = await LivechatVisitors.findOneById(association.visitorId);\n\n\tif (!visitor) {\n\t\tthrow new Error('error-visitor-not-found');\n\t}\n\n\tconst room = await LivechatRooms.findOneOpenByContactChannelVisitor(association);\n","sourceCodeStart":1,"sourceCodeEnd":30,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/ee/server/api/v1/omnichannel/lib/contacts.ts#L1-L30","documentation":"changeContactBlockStatus flips a contact's channel block flag via LivechatContacts.setChannelBlockStatus(visitor, block). When the update matches no document (modifiedCount === 0) it throws plain Error('error-contact-not-found'): no contact record carries the given visitor association (visitorId + channel).","triggerScenarios":"Omnichannel contact block/unblock flow called with a visitorId + channel pair that matches no registered contact; or the contact was deleted between listing and blocking.","commonSituations":"Visitor exists but the contact-identification flow never created a contact record; passing a visitorId where the contact's stored association differs (wrong channel key); concurrent contact deletion.","solutions":["Look the contact up by the same visitor association first and register it if missing","Pass the exact visitorId + channel values used when the contact was created","Re-run contact registration, then retry the block/unblock"],"exampleFix":"// before\nawait changeContactBlockStatus({ visitor: { visitorId, channel }, block: true }); // → error-contact-not-found\n\n// after\nconst contact = await LivechatContacts.findOneByVisitorAssociation({ visitorId, channel });\nif (!contact) await registerContact({ visitorId, channel });\nawait changeContactBlockStatus({ visitor: { visitorId, channel }, block: true });","handlingStrategy":"validation","validationCode":"import { LivechatContacts } from '@rocket.chat/models';\n\nconst contact = await LivechatContacts.findOneByVisitorAssociation({ visitorId, channel });\nif (!contact) {\n  throw new Error('no contact for this visitor association - register the contact first');\n}\nawait changeContactBlockStatus({ visitor: { visitorId, channel }, block: true });","typeGuard":null,"tryCatchPattern":"try {\n  await changeContactBlockStatus({ visitor: association, block });\n} catch (error) {\n  if (error instanceof Error && error.message === 'error-contact-not-found') {\n    // contact deleted concurrently or never registered: re-register then retry once\n    await registerContact(association);\n    return changeContactBlockStatus({ visitor: association, block });\n  }\n  throw error;\n}","preventionTips":["Register the contact before offering block/unblock actions","Reuse the exact visitorId + channel pair from contact creation","Handle concurrent deletion — modifiedCount can change between check and update"],"tags":["omnichannel","contacts","livechat","not-found"],"backgroundTag":"resource-not-found","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}