RocketChat/Rocket.Chat · error · Meteor.Error

error-action-not-allowed

error-action-not-allowed

Error message

This is an enterprise feature

What it means

The getReadReceipts Meteor method (apps/meteor/ee/server/meteor-methods/getReadReceipts.ts:21) is an enterprise feature gated on the 'message-read-receipt' license module. When License.hasModule('message-read-receipt') is false (Community edition, or an Enterprise license without that module) the method throws Meteor.Error('error-action-not-allowed', 'This is an enterprise feature') before any other validation.

Solutions

  1. Install/activate an Enterprise license that includes the 'message-read-receipt' module
  2. Feature-detect before invoking: guard the UI/action with License.hasModule('message-read-receipt') on the server or license state on the client
  3. If it cannot be licensed, remove or disable the read-receipt entry point in the client so users never trigger it

Example fix

// before
Meteor.call('getReadReceipts', { messageId }, (err, receipts) => { ... });

// after
if (!hasLicenseModule('message-read-receipt')) {
	// hide the action instead of calling the method
	return null;
}
Meteor.call('getReadReceipts', { messageId }, (err, receipts) => { ... });
Defensive patterns

Strategy: validation

Validate before calling

import { License } from '@rocket.chat/license';

if (!License.hasModule('message-read-receipt')) {
	// hide the read-receipt action; calling the method will throw
	return;
}
Meteor.call('getReadReceipts', { messageId }, cb);

Try / catch

Meteor.call('getReadReceipts', { messageId }, (err, receipts) => {
	if (err) {
		if (err.error === 'error-action-not-allowed') {
			// enterprise feature unavailable — hide the entry point
			return;
		}
		throw err;
	}
});

Prevention

When it happens

Trigger: Invoking the getReadReceipts DDP method on a workspace whose license does not include the 'message-read-receipt' module. The method is also deprecated since 9.0.0 in favor of the REST endpoint /v1/chat.getMessageReadReceipts, which is gated by the same license module.

Common situations: Running Community edition and clicking 'read receipts' in the message menu; trial license expired; Enterprise license renewed without the read-receipt module; apps/integrations calling the method programmatically.

Related errors


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

Appendix: source

Thrown at apps/meteor/ee/server/meteor-methods/getReadReceipts.ts:21

import { License } from '@rocket.chat/license';
import { Messages } from '@rocket.chat/models';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';

import { canAccessRoomIdAsync } from '../../../server/lib/authorization/canAccessRoom';
import { methodDeprecationLogger } from '../../../server/lib/deprecationWarningLogger';
import { ReadReceipt } from '../lib/message-read-receipt/ReadReceipt';

declare module '@rocket.chat/ddp-client' {
	// eslint-disable-next-line @typescript-eslint/naming-convention
	interface ServerMethods {
		getReadReceipts(options: { messageId: IMessage['_id'] }): IReadReceiptWithUser[];
	}
}

export const getReadReceiptsFunction = async function (messageId: IMessage['_id'], userId: string): Promise<IReadReceiptWithUser[]> {
	if (!License.hasModule('message-read-receipt')) {
		throw new Meteor.Error('error-action-not-allowed', 'This is an enterprise feature', { method: 'getReadReceipts' });
	}
	check(messageId, String);

	const message = await Messages.findOneById(messageId, { projection: { _id: 1, rid: 1, receiptsArchived: 1 } });
	if (!message) {
		throw new Meteor.Error('error-invalid-message', 'Invalid message', {
			method: 'getReadReceipts',
		});
	}

	if (!(await canAccessRoomIdAsync(message.rid, userId))) {
		throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'getReadReceipts' });
	}

	return ReadReceipt.getReceipts(message);
};

Meteor.methods<ServerMethods>({

View on GitHub (pinned to b2c16d5842)