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
- Apply an Enterprise license that includes contact-id-verification.
- Call ensureSingleContactLicense() up front and degrade gracefully when it throws, instead of letting it surface mid-flow.
- Disable the UI entry points that trigger contact verification when the module is absent.
- 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
- Centralize license probes for contact verification in one guard the UI consults before showing the feature.
- Disable related omnichannel automations when the module is not licensed.
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
- error-max-rooms-per-guest-reached
- error-action-not-allowed
- error-action-not-allowed
- error-contact-not-found
- Trigger is not configured to use an external service
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/e0321e77779ab83d.
Report an issue: GitHub.