RocketChat/Rocket.Chat · error · Error

error-verifying-contact-channel

Error message

error-verifying-contact-channel

What it means

Thrown by _verifyContactChannel when the MongoDB transaction that updates the contact, marks the room verified, and merges contacts fails and cannot be retried. The function already retries twice on transient errors (shouldRetryTransaction), so this error means the transaction genuinely failed (write conflict that exhausted retries, validation error, or a non-transient fault). The catch aborts the transaction, logs the underlying error, and re-throws this generic Error.

Source

Thrown at apps/meteor/ee/server/patches/verifyContactChannel.ts:53

		await LivechatContacts.updateFromUpdaterByAssociation({ visitorId, source: room.source }, updater, { session });

		await LivechatRooms.update({ _id: roomId }, { $set: { verified: true } }, { session });
		logger.debug({ msg: 'Merging contacts', contactId, visitorId, roomId });

		const mergeContactsResult = await mergeContacts(contactId, { visitorId, source: room.source }, session);

		await session.commitTransaction();

		return mergeContactsResult;
	} catch (e) {
		await session.abortTransaction();
		if (shouldRetryTransaction(e) && attempts > 0) {
			logger.debug({ msg: 'Retrying to verify contact channel', contactId, visitorId, roomId });
			return _verifyContactChannel(params, room, attempts - 1);
		}

		logger.error({ msg: 'Error verifying contact channel', contactId, visitorId, roomId, error: e });
		throw new Error('error-verifying-contact-channel');
	} finally {
		await session.endSession();
	}
}

export const runVerifyContactChannel = async (
	_next: any,
	params: {
		contactId: string;
		field: string;
		value: string;
		visitorId: string;
		roomId: string;
	},
): Promise<ILivechatContact | null> => {
	const { roomId, contactId, visitorId } = params;

	const room = await LivechatRooms.findOneById(roomId);

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Inspect the logged 'error: e' in the server log to find the underlying MongoDB error code.
  2. For write conflicts, reduce contention on the same contact/visitor or increase the retry count / back-off.
  3. Ensure the deployment runs a replica set (required for multi-document transactions).
  4. For validation errors, fix the data shape produced by setVerifiedUpdateQuery/setFieldAndValueUpdateQuery.
Defensive patterns

Strategy: retry

Try / catch

try {
  await verifyContactChannel(params);
} catch (e) {
  if (e.message === 'error-verifying-contact-channel') {
    // surface a generic 'verification failed, please retry' and log correlation id
  } else throw e;
}

Prevention

When it happens

Trigger: A write conflict (WriteConflict/error code 112) that survives both retries; a MongoDB transaction abort due to a constraint/validation failure inside the transaction; loss of the replica-set primary mid-transaction; an error thrown by mergeContacts inside the transaction that is not retryable.

Common situations: High concurrency on the same visitor/contact causing repeated write conflicts; MongoDB standalone (no replica set) where transactions are unsupported; long-running transactions hitting the 60s default timeout; schema validator rejecting the update query.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12). Data as JSON: /api/errors/437e33311ac7b33f. Report an issue: GitHub.