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
- Install/activate an Enterprise license that includes the 'message-read-receipt' module
- Feature-detect before invoking: guard the UI/action with License.hasModule('message-read-receipt') on the server or license state on the client
- 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
- Gate read-receipt UI on the license module so unlicensed users never trigger the call
- Prefer the REST endpoint /v1/chat.getMessageReadReceipts and check its license-gated behavior in integration tests
- Verify license entitlements after renewals/trials expire
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
- error-action-not-allowed
- error-mac-limit-reached
- error-action-not-allowed
- error-action-not-allowed
- error-ai-not-enabled
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)