{"record":{"id":"c60b58ad4f3d26f4","repo":"RocketChat/Rocket.Chat","slug":"error-action-not-allowed","errorCode":"error-action-not-allowed","errorMessage":"This is an enterprise feature","messagePattern":"This is an enterprise feature","errorType":"error_code","errorClass":"Meteor.Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/ee/server/api/chat.ts","lineNumber":52,"sourceCode":"\t},\n\trequired: ['receipts', 'success'],\n\tadditionalProperties: false,\n});\n\nAPI.v1.get(\n\t'chat.getMessageReadReceipts',\n\t{\n\t\tauthRequired: true,\n\t\tquery: isChatGetMessageReadReceiptsProps,\n\t\tresponse: {\n\t\t\t200: getMessageReadReceiptsResponseSchema,\n\t\t\t400: validateBadRequestErrorResponse,\n\t\t\t401: validateUnauthorizedErrorResponse,\n\t\t},\n\t},\n\tasync function action() {\n\t\tif (!License.hasModule('message-read-receipt')) {\n\t\t\tthrow new Meteor.Error('error-action-not-allowed', 'This is an enterprise feature');\n\t\t}\n\n\t\tconst { messageId } = this.queryParams;\n\n\t\treturn API.v1.success({\n\t\t\treceipts: await getReadReceiptsFunction(messageId, this.userId),\n\t\t});\n\t},\n);\n","sourceCodeStart":34,"sourceCodeEnd":62,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/ee/server/api/chat.ts#L34-L62","documentation":"Meteor.Error('error-action-not-allowed', 'This is an enterprise feature') thrown by chat.getMessageReadReceipts when License.hasModule('message-read-receipt') is false. The endpoint exists on all builds but only serves requests on licensed Enterprise workspaces; otherwise it rejects with 403-shaped not-allowed.","triggerScenarios":"GET /v1/chat.getMessageReadReceipts?messageId=... on a Community workspace or one whose license does not include the message-read-receipt module.","commonSituations":"Apps/integrations written against EE features and deployed to Community; trial license expiring so hasModule flips to false; feature flags not purchased.","solutions":["Install/renew an Enterprise license that includes the message-read-receipt module.","Feature-detect before use (GET /v1/license or check the module list) and hide read-receipt UI on unlicensed workspaces.","If read receipts are not essential, remove the call on Community deployments."],"exampleFix":"// before\nconst { receipts } = await GET('chat.getMessageReadReceipts')({ messageId }); // 403 on CE\n\n// after\nconst { modules } = await GET('license')();\nif (!modules.includes('message-read-receipt')) throw new Error('Feature not licensed');\nconst { receipts } = await GET('chat.getMessageReadReceipts')({ messageId });","handlingStrategy":"validation","validationCode":"const hasReadReceiptModule = async (): Promise<boolean> =>\n\t(await GET('license')()).modules.includes('message-read-receipt');","typeGuard":"const isEnterpriseFeatureError = (error: unknown): boolean =>\n\tBoolean(error && typeof error === 'object' && 'error' in error && (error as { error?: string }).error === 'error-action-not-allowed' && /enterprise feature/i.test(String((error as { reason?: string }).reason ?? '')));","tryCatchPattern":"try {\n\tconst { receipts } = await GET('chat.getMessageReadReceipts')({ messageId });\n} catch (error) {\n\tif (isEnterpriseFeatureError(error)) {\n\t\thideReadReceiptsUI(); // unlicensed workspace — degrade gracefully, do not retry\n\t\treturn;\n\t}\n\tthrow error;\n}","preventionTips":["Feature-detect the license module before showing read-receipt affordances.","Keep a licensed test workspace for EE integration tests.","Watch license expiry: hasModule flips off when renewals lapse."],"tags":["ee","license","read-receipts","rest-api"],"backgroundTag":"enterprise-license-required","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}