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

  1. Manage attributes in the external store (e.g. the LDAP directory attributes mapped in settings) instead of the local ABAC API.
  2. If local storage is intended, remove/reconfigure the external attribute source so isExternalAttributeStore() returns false.
  3. 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

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)