RocketChat/Rocket.Chat · error
error-not-authorized
error-not-authorized
Error message
error-not-authorized
What it means
Error `error-not-authorized` thrown by ldap.syncNow when the authenticated user lacks the `sync-auth-services-users` permission. Only users holding that permission (typically admins) may trigger an LDAP sync; everyone else is rejected after auth succeeds.
Solutions
- Grant sync-auth-services-users to the calling user's role (Admin > Permissions), then retry.
- Use an administrator account for LDAP sync operations.
- Check the permission via the roles API in automation before calling sync.
Example fix
// before
await POST('ldap.syncNow'); // as user without permission -> error-not-authorized
// after
await POST('permissions.update', { permissions: [{ _id: 'sync-auth-services-users', roles: ['ldap-sync-bot'] }] });
await POST('ldap.syncNow'); Defensive patterns
Strategy: validation
Validate before calling
const canSyncAuthServices = async (userId: string): Promise<boolean> =>
(await GET('roles.list')()).roles.some((role) => role._id === 'admin'); // or query permissions for the caller Type guard
const isNotAuthorized = (error: unknown): boolean =>
Boolean(error && typeof error === 'object' && 'message' in error && (error as Error).message.includes('error-not-authorized')); Try / catch
try {
await POST('ldap.syncNow');
} catch (error) {
if (isNotAuthorized(error)) {
throw new ForbiddenError('Caller needs sync-auth-services-users permission');
}
throw error;
} Prevention
- Run LDAP sync operations as a user holding sync-auth-services-users (typically admin).
- Grant the permission explicitly to service accounts used for directory automation.
- Re-check role permissions after role refactors.
When it happens
Trigger: POST /v1/ldap.syncNow with valid credentials of a non-admin or an admin whose role lost sync-auth-services-users.
Common situations: Custom roles without the permission calling the sync; permission removed during role refactors; automation using a service account that was never granted it.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- error-invalid-user
- LDAP_disabled
- error-abac-attribute-store-external
- error-abac-not-enabled
- error-action-not-allowed
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/ac31c492355576eb.
Report an issue: GitHub.
Appendix: source
Thrown at apps/meteor/ee/server/api/ldap.ts:36
API.v1.post(
'ldap.syncNow',
{
authRequired: true,
forceTwoFactorAuthenticationForNonEnterprise: true,
twoFactorRequired: true,
response: {
200: ldapSyncNowResponseSchema,
400: validateBadRequestErrorResponse,
401: validateUnauthorizedErrorResponse,
},
},
async function action() {
if (!this.userId) {
throw new Error('error-invalid-user');
}
if (!(await hasPermissionAsync(this.user, 'sync-auth-services-users'))) {
throw new Error('error-not-authorized');
}
if (settings.get('LDAP_Enable') !== true) {
throw new Error('LDAP_disabled');
}
await LDAPEnterprise.sync();
await LDAPEnterprise.syncAvatarAndAbacAttributes();
return API.v1.success({
message: 'Sync_in_progress' as const,
});
},
);
View on GitHub (pinned to b2c16d5842)