RocketChat/Rocket.Chat · warning · Meteor.Error

error-action-not-allowed

error-action-not-allowed

Error message

This is an enterprise feature

What it means

Thrown by the GET chat.getMessageReadReceipts REST endpoint when the current server license does not include the 'message-read-receipt' module. Rocket.Chat gates message read-receipt visibility behind an Enterprise license; community/ Starter licenses do not expose this data. The check runs inside the handler after authentication, so a valid auth token is still required first. It surfaces to the REST client as a Meteor.Error with code error-action-not-allowed.

Source

Thrown at apps/meteor/ee/server/api/chat.ts:52

	},
	required: ['receipts', 'success'],
	additionalProperties: false,
});

API.v1.get(
	'chat.getMessageReadReceipts',
	{
		authRequired: true,
		query: isChatGetMessageReadReceiptsProps,
		response: {
			200: getMessageReadReceiptsResponseSchema,
			400: validateBadRequestErrorResponse,
			401: validateUnauthorizedErrorResponse,
		},
	},
	async function action() {
		if (!License.hasModule('message-read-receipt')) {
			throw new Meteor.Error('error-action-not-allowed', 'This is an enterprise feature');
		}

		const { messageId } = this.queryParams;

		return API.v1.success({
			receipts: await getReadReceiptsFunction(messageId, this.userId),
		});
	},
);

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Apply a valid Enterprise license that includes the message-read-receipt module via Administration > Workspace > License (or the Cloud workspace portal).
  2. Verify the active module with the license API / admin UI before calling this endpoint.
  3. If Enterprise is not available, stop calling this endpoint and fall back to message status fields (e.g. unread indicators) that are not license-gated.
  4. Check for license expiration and renew if needed.

Example fix

// before: unconditional call
const res = await fetch('/v1/chat.getMessageReadReceipts?messageId=' + id);

// after: gate on license capability client-side / surface upgrade prompt
const hasModule = await licenseHasModule('message-read-receipt');
if (!hasModule) {
  throw new Error('Read receipts require an Enterprise license with the message-read-receipt module.');
}
const res = await fetch('/v1/chat.getMessageReadReceipts?messageId=' + id);
Defensive patterns

Strategy: validation

Validate before calling

// Check the license module before calling the endpoint
async function canUseReadReceipts(): Promise<boolean> {
  const res = await fetch('/api/v1/license.get', { headers: authHeaders() });
  const { license } = await res.json();
  return Array.isArray(license?.modules) && license.modules.includes('message-read-receipt');
}
if (!(await canUseReadReceipts())) {
  throw new Error('message-read-receipt module not licensed');
}

Type guard

function hasReadReceiptLicense(modules: unknown): modules is string[] {
  return Array.isArray(modules) && modules.includes('message-read-receipt');
}

Try / catch

try {
  return await api.get('chat.getMessageReadReceipts', { messageId });
} catch (e) {
  if (isMeteorError(e, 'error-action-not-allowed')) {
    return { receipts: [], reason: 'not-licensed' };
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling GET /v1/chat.getMessageReadReceipts?messageId=<id> on a server whose license lacks the message-read-receipt module (License.hasModule('message-read-receipt') returns false). Happens on self-hosted Community editions, expired Enterprise trials, or licenses that predate the module.

Common situations: Developers running Rocket.Chat CE expecting parity with EE APIs; Enterprise trial expired silently; license applied to wrong workspace; feature flag disabled by license tier downgrade.

Related errors


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