RocketChat/Rocket.Chat · warning · Error

error-action-not-allowed

Error message

error-action-not-allowed

What it means

Thrown by ensureSingleContactLicense when the license lacks the 'contact-id-verification' module. Single-contact verification (binding a visitor to one verified contact) is an Enterprise feature; callers must check the license before using contact-verification APIs. Plain Error, code 'error-action-not-allowed'.

Source

Thrown at apps/meteor/ee/server/api/v1/omnichannel/lib/contacts.ts:18

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);

	if (!room) {
		return;
	}

	return closeRoom({ room, visitor, comment: i18n.t('close-blocked-room-comment'), user });
}

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Apply an Enterprise license that includes contact-id-verification.
  2. Call ensureSingleContactLicense() up front and degrade gracefully when it throws, instead of letting it surface mid-flow.
  3. Disable the UI entry points that trigger contact verification when the module is absent.
  4. Verify the active module list via the workspace/license API.

Example fix

// before: feature used unconditionally
await verifyContact(visitor);

// after: probe capability first
try {
  ensureSingleContactLicense();
  await verifyContact(visitor);
} catch (e) {
  // feature not licensed; disable flow
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Probe license capability up front
import { License } from '@rocket.chat/license';
function contactVerificationAvailable(): boolean {
  return License.hasModule('contact-id-verification');
}
if (!contactVerificationAvailable()) {
  // disable flow gracefully
  return;
}

Try / catch

try {
  ensureSingleContactLicense();
  await runContactVerificationFlow();
} catch (e) {
  if (e.message === 'error-action-not-allowed') {
    disableContactVerificationUi();
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Invoking any omnichannel code path that calls ensureSingleContactLicense (contact verification, block/unblock flows tied to verified contacts) on a server without the contact-id-verification license module.

Common situations: CE deployment; Enterprise license without the contact-id-verification add-on; trial expired; feature gated off by license tier.

Related errors


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