RocketChat/Rocket.Chat · error · Error

error-not-authorized

error-not-authorized

Error message

error-not-authorized

What it means

Thrown by POST ldap.syncNow when the authenticated user lacks the 'sync-auth-services-users' permission. Rocket.Chat gates LDAP sync operations behind this permission to restrict who can trigger a directory-wide sync. The throw is a plain Error with code 'error-not-authorized' and occurs after the user-id check passes.

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 f9d3ec372b)

Solutions

  1. Grant 'sync-auth-services-users' to the calling user's role (Administration > Permissions).
  2. Re-authenticate as a user that already holds the permission (e.g. the main admin account).
  3. Verify the permission grant was not removed by a permissions import/migration.
  4. Use an API token scoped to an authorized admin user.

Example fix

// before: calling with a role lacking the permission
POST /v1/ldap.syncNow  (user role: 'livechat-manager')

// after: grant the permission to that role, or call with an admin token
POST /v1/ldap.syncNow  (X-Auth-Token of a user with 'sync-auth-services-users')
Defensive patterns

Strategy: validation

Validate before calling

// Verify the caller holds the permission before calling
async function canSyncLdap(user: { _id: string }): Promise<boolean> {
  // GET /v1/roles.list + GET /v1/permissions, or use server-side hasPermission
  return await serverHasPermission(user._id, 'sync-auth-services-users');
}
if (!(await canSyncLdap(currentUser))) {
  throw new Error('missing sync-auth-services-users permission');
}

Try / catch

try {
  await api.post('ldap.syncNow', {});
} catch (e) {
  if (e.message === 'error-not-authorized') {
    notifyInsufficientPermission('sync-auth-services-users');
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: An authenticated admin or regular user calls POST /v1/ldap.syncNow but their roles do not include a role granted 'sync-auth-services-users'. Common when a non-super-admin tries the sync, or after permissions were restructured and the role lost the grant.

Common situations: Custom role used for admin tasks but missing the sync permission; permissions reset during an upgrade; user authenticated but with read-only admin scope.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12). Data as JSON: /api/errors/ac31c492355576eb. Report an issue: GitHub.