RocketChat/Rocket.Chat · error · Meteor.Error

error-action-not-allowed

error-action-not-allowed

Error message

This is an enterprise feature

What it means

Thrown by the getReadReceipts DDP method when License.hasModule('message-read-receipt') returns false. Read receipts with user attribution are an Enterprise-only module; on a Community install (or a license without that module) the method refuses before doing any work. Code is 'error-action-not-allowed'.

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

Solutions

  1. Apply an Enterprise license that includes the message-read-receipt module.
  2. If Enterprise is not available, disable/avoid UI that calls getReadReceipts and rely on the core read-receipt indicators only.
  3. Confirm the license is loaded and not expired via Administration > License.
Defensive patterns

Strategy: validation

Validate before calling

import { License } from '@rocket.chat/license';
if (!License.hasModule('message-read-receipt')) {
  disableReadReceiptListUI();
  return;
}
const receipts = await getReadReceiptsFunction(messageId, uid);

Type guard

function readReceiptsLicensed(): boolean {
  return License.hasModule('message-read-receipt');
}

Try / catch

try {
  await Meteor.callAsync('getReadReceipts', { messageId });
} catch (e) {
  if (isMeteorError(e, 'error-action-not-allowed')) {
    notifyUser('Read-receipt details require an Enterprise license.');
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling the getReadReceipts method (or any feature that resolves read-receipt user lists) on a workspace whose license does not include the 'message-read-receipt' module.

Common situations: Community edition deployment; Enterprise license expired or downgraded; dev/test instance without a license file loaded.

Related errors


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