RocketChat/Rocket.Chat · error · AbacAttributeStoreExternalError
error-abac-attribute-store-external
error-abac-attribute-store-external
Error message
error-abac-attribute-store-external
What it means
AbacAttributeStoreExternalError (`error-abac-attribute-store-external`) thrown by assertLocalAttributeStore in the EE ABAC REST endpoints. Attribute-definition write endpoints (POST/PUT abac/attributes...) manage Rocket.Chat's local attribute store; when the deployment sources attributes from an external store (Abac.isExternalAttributeStore() resolves true, e.g. attributes synced from LDAP), local CRUD is rejected.
Solutions
- Manage attributes in the external store (e.g. the LDAP directory attributes mapped in settings) instead of the local ABAC API.
- If local storage is intended, remove/reconfigure the external attribute source so isExternalAttributeStore() returns false.
- Make provisioning scripts skip these endpoints when an external store is configured.
Example fix
// before
await POST('abac/attributes', definition); // 400 error-abac-attribute-store-external
// after
if (await Abac.isExternalAttributeStore()) {
throw new Error('Manage attributes in the external (LDAP) store');
}
await POST('abac/attributes', definition); Defensive patterns
Strategy: validation
Validate before calling
const isLocalAttributeStore = async (): Promise<boolean> => !(await Abac.isExternalAttributeStore());
// guard before calling local attribute-definition endpoints
if (!(await isLocalAttributeStore())) throw new Error('Attributes are managed externally'); Type guard
const isExternalStoreError = (error: unknown): boolean =>
Boolean(error && typeof error === 'object' && 'error' in error && (error as { error: string }).error === 'error-abac-attribute-store-external'); Try / catch
try {
await POST('abac/attributes', definition);
} catch (error) {
if (isExternalStoreError(error)) {
// route to the external (LDAP) attribute source; never retry locally
throw new Error('Manage ABAC attributes in the external store');
}
throw error;
} Prevention
- Detect the store mode (Abac.isExternalAttributeStore) before any local attribute CRUD.
- Point attribute provisioning at the LDAP directory when attributes are externally sourced.
- Document store mode per environment so scripts target the right surface.
When it happens
Trigger: Calling POST /v1/abac/attributes or PUT /v1/abac/attributes/:_id on a workspace whose ABAC attributes are provided by an external identity store; adding the guard after configuring LDAP-backed attributes.
Common situations: Admins scripting attribute definitions against an LDAP-integrated workspace; migration tooling replaying local-store payloads on an externally-backed deployment.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/f4f07a08d9a056bb.
Report an issue: GitHub.
Appendix: source
Thrown at apps/meteor/ee/server/api/abac/index.ts:45
GETAbacPdpHealthErrorResponseSchema,
} from './schemas';
import { API } from '../../../../server/api';
import type { ExtractRoutesFromAPI } from '../../../../server/api/ApiClass';
import { getPaginationItems } from '../../../../server/api/lib/getPaginationItems';
import { settings } from '../../../../server/settings';
const getActorFromUser = (user?: IUser | null): AbacActor | undefined =>
user?._id
? {
_id: user._id,
username: user.username,
name: user.name,
}
: undefined;
const assertLocalAttributeStore = async (): Promise<void> => {
if (await Abac.isExternalAttributeStore()) {
throw new AbacAttributeStoreExternalError();
}
};
const abacEndpoints = API.v1
.post(
'abac/rooms/:rid/attributes',
{
authRequired: true,
permissionsRequired: ['abac-management', 'manage-abac-admin-rooms'],
body: POSTRoomAbacAttributesBodySchema,
response: {
200: GenericSuccessSchema,
401: validateUnauthorizedErrorResponse,
400: GenericErrorSchema,
403: validateUnauthorizedErrorResponse,
},
license: ['abac'],
},View on GitHub (pinned to b2c16d5842)