RocketChat/Rocket.Chat · error · Error
error-contact-not-found
Error message
error-contact-not-found
What it means
Thrown by changeContactBlockStatus when LivechatContacts.setChannelBlockStatus reports zero modified documents. This means no contact matched the supplied visitor association (channel + visitorId), so the block/unblock operation had no effect. Plain Error, code 'error-contact-not-found'.
Source
Thrown at apps/meteor/ee/server/api/v1/omnichannel/lib/contacts.ts:12
import type { IUser, ILivechatContactVisitorAssociation } from '@rocket.chat/core-typings';
import { License } from '@rocket.chat/license';
import { LivechatContacts, LivechatRooms, LivechatVisitors } from '@rocket.chat/models';
import { i18n } from '../../../../../../server/lib/i18n';
import { closeRoom } from '../../../../../../server/lib/omnichannel/closeRoom';
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);
View on GitHub (pinned to f9d3ec372b)
Solutions
- Verify the contact exists: query LivechatContacts by the same visitor association before calling.
- Refresh the visitorId/channel from the upstream source and retry.
- Check that the correct workspace/DB is targeted (sharded/multi-instance).
- Handle the no-op case gracefully if the contact may already be removed.
Example fix
// before: blind update
await changeContactBlockStatus({ visitor: assoc, block: true });
// after: verify existence first
const existing = await LivechatContacts.findOneByVisitorAssociation(assoc);
if (!existing) throw new NotFoundError('contact');
await changeContactBlockStatus({ visitor: assoc, block: true }); Defensive patterns
Strategy: validation
Validate before calling
// Verify the contact exists before toggling block status
import { LivechatContacts } from '@rocket.chat/models';
const existing = await LivechatContacts.findOneByVisitorAssociation(visitor);
if (!existing) {
throw new NotFoundError('contact');
}
await changeContactBlockStatus({ visitor, block }); Try / catch
try {
await changeContactBlockStatus({ visitor, block });
} catch (e) {
if (e.message === 'error-contact-not-found') {
// refresh contact data and retry once, or skip
return { ok: false, reason: 'contact-missing' };
}
throw e;
} Prevention
- Do not cache visitor associations across long-lived sessions; refetch before mutating.
- Treat a zero-modifiedCount result as a soft no-op when the contact may already be removed.
When it happens
Trigger: Calling changeContactBlockStatus with a visitor association whose visitorId or channel does not match any LivechatContacts document; contact was deleted between lookup and update; wrong tenant/workspace context.
Common situations: Stale visitorId cached on the client after a contact merge; channel identifier typo; contact deleted by another process; multi-instance setup querying the wrong DB.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/f92f99c07f3d15c8.
Report an issue: GitHub.