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

  1. Confirm the visitor exists via LivechatVisitors.findOneById before calling closeBlockedRoom.
  2. Reconcile LivechatVisitors with LivechatContacts if records are inconsistent.
  3. If the visitor was intentionally deleted, close the room via a different path (e.g. manual close) and clean up the orphaned contact association.
  4. 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

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.