{"record":{"id":"f4f07a08d9a056bb","repo":"RocketChat/Rocket.Chat","slug":"error-abac-attribute-store-external","errorCode":"error-abac-attribute-store-external","errorMessage":"error-abac-attribute-store-external","messagePattern":"error-abac-attribute-store-external","errorType":"http","errorClass":"AbacAttributeStoreExternalError","httpStatus":400,"severity":"error","filePath":"apps/meteor/ee/server/api/abac/index.ts","lineNumber":45,"sourceCode":"\tGETAbacPdpHealthErrorResponseSchema,\n} from './schemas';\nimport { API } from '../../../../server/api';\nimport type { ExtractRoutesFromAPI } from '../../../../server/api/ApiClass';\nimport { getPaginationItems } from '../../../../server/api/lib/getPaginationItems';\nimport { settings } from '../../../../server/settings';\n\nconst getActorFromUser = (user?: IUser | null): AbacActor | undefined =>\n\tuser?._id\n\t\t? {\n\t\t\t\t_id: user._id,\n\t\t\t\tusername: user.username,\n\t\t\t\tname: user.name,\n\t\t\t}\n\t\t: undefined;\n\nconst assertLocalAttributeStore = async (): Promise<void> => {\n\tif (await Abac.isExternalAttributeStore()) {\n\t\tthrow new AbacAttributeStoreExternalError();\n\t}\n};\n\nconst abacEndpoints = API.v1\n\t.post(\n\t\t'abac/rooms/:rid/attributes',\n\t\t{\n\t\t\tauthRequired: true,\n\t\t\tpermissionsRequired: ['abac-management', 'manage-abac-admin-rooms'],\n\t\t\tbody: POSTRoomAbacAttributesBodySchema,\n\t\t\tresponse: {\n\t\t\t\t200: GenericSuccessSchema,\n\t\t\t\t401: validateUnauthorizedErrorResponse,\n\t\t\t\t400: GenericErrorSchema,\n\t\t\t\t403: validateUnauthorizedErrorResponse,\n\t\t\t},\n\t\t\tlicense: ['abac'],\n\t\t},","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/ee/server/api/abac/index.ts#L27-L63","documentation":"Thrown as AbacAttributeStoreExternalError ('error-abac-attribute-store-external') by assertLocalAttributeStore() when Abac.isExternalAttributeStore() is true. Attribute-definition mutation endpoints (create/update/delete/get-in-use of abac/attributes) are only valid when the local store holds attribute definitions; an external PDP/store must be edited through its own system, so these endpoints refuse to mutate locally.","triggerScenarios":"Workspace is configured to use an external ABAC attribute store (PDP) and the client calls POST/PUT/DELETE/GET abac/attributes/:_id or abac/attributes/:key/is-in-use — assertLocalAttributeStore throws before touching the local collection.","commonSituations":"Admin switched ABAC to an external attribute store but the UI/API caller still issues local attribute-mutation calls; migration in progress; misconfigured store selection.","solutions":["Manage attribute definitions in the configured external attribute store/PDP instead of via these REST endpoints.","If local management is required, switch the ABAC attribute store back to local (admin ABAC settings).","Update the admin UI to disable local attribute editing controls when the store is external."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Callers should check the store mode before issuing local attribute mutations.\nGET /api/v1/abac/pdp/health or an admin settings fetch to determine if the store is external;\nif external, disable local attribute CRUD controls.","typeGuard":null,"tryCatchPattern":"try {\n  await addAbacAttribute(...);\n} catch (e) {\n  if (e instanceof AbacAttributeStoreExternalError) {\n    // tell user to manage attributes in the external store\n  } else throw e;\n}","preventionTips":["When ABAC uses an external attribute store, hide local attribute-edit UI.","Document which operations are local-only vs external.","During store migrations, freeze attribute-definition writes until settled."],"tags":["ee","abac","server","rest-api","attribute-store"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}