RocketChat/Rocket.Chat · error · Error
error-visitor-not-found
Error message
error-visitor-not-found
What it means
Thrown by closeBlockedRoom when LivechatVisitors.findOneById(association.visitorId) returns null. The blocked-contact room closure requires a valid visitor record to attribute the closure; a missing visitor halts the operation. Plain Error, code 'error-visitor-not-found'.
Source
Thrown at apps/meteor/ee/server/api/v1/omnichannel/lib/contacts.ts:26
export async function changeContactBlockStatus({ block, visitor }: { visitor: ILivechatContactVisitorAssociation; block: boolean }) {
const result = await LivechatContacts.setChannelBlockStatus(visitor, block);
if (!result.modifiedCount) {
throw new Error('error-contact-not-found');
}
}
export function ensureSingleContactLicense() {
if (!License.hasModule('contact-id-verification')) {
throw new Error('error-action-not-allowed');
}
}
export async function closeBlockedRoom(association: ILivechatContactVisitorAssociation, user: IUser) {
const visitor = await LivechatVisitors.findOneById(association.visitorId);
if (!visitor) {
throw new Error('error-visitor-not-found');
}
const room = await LivechatRooms.findOneOpenByContactChannelVisitor(association);
if (!room) {
return;
}
return closeRoom({ room, visitor, comment: i18n.t('close-blocked-room-comment'), user });
}
View on GitHub (pinned to f9d3ec372b)
Solutions
- Confirm the visitor exists via LivechatVisitors.findOneById before calling closeBlockedRoom.
- Reconcile LivechatVisitors with LivechatContacts if records are inconsistent.
- If the visitor was intentionally deleted, close the room via a different path (e.g. manual close) and clean up the orphaned contact association.
- Validate the visitorId format/length against the stored collection.
Example fix
// before: assume visitor present
await closeBlockedRoom(assoc, user);
// after: precondition check
const visitor = await LivechatVisitors.findOneById(assoc.visitorId);
if (!visitor) {
// reconcile or skip; do not call closeBlockedRoom
return;
}
await closeBlockedRoom(assoc, user); Defensive patterns
Strategy: validation
Validate before calling
// Verify visitor exists before closing the blocked room
import { LivechatVisitors } from '@rocket.chat/models';
const visitor = await LivechatVisitors.findOneById(association.visitorId);
if (!visitor) {
// reconcile or skip; do not call closeBlockedRoom
return { ok: false, reason: 'visitor-missing' };
}
await closeBlockedRoom(association, user); Try / catch
try {
await closeBlockedRoom(association, user);
} catch (e) {
if (e.message === 'error-visitor-not-found') {
// orphaned blocked room: close via fallback path
await fallbackCloseRoom(association, user);
return;
}
throw e;
} Prevention
- Reconcile LivechatVisitors with LivechatContacts after imports/merges.
- Validate visitorId format and existence before any room lifecycle operation.
When it happens
Trigger: Calling closeBlockedRoom with a visitor association whose visitorId does not exist in LivechatVisitors; visitor was deleted while a blocked room was still open; visitorId passed as a string ID that does not match the stored ObjectId string form.
Common situations: Race condition: visitor purged after the block was set; stale association cached; data inconsistency between LivechatContacts and LivechatVisitors; import that created contacts without matching visitors.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/985695e06f666ba4.
Report an issue: GitHub.