RocketChat/Rocket.Chat · error · Meteor.Error
LDAP-login-error
LDAP-login-error
Error message
LDAP Authentication succeeded, but there's already an existing user with provided username [${user.username}] in Mongo. What it means
Thrown by LDAP Manager.loginExistingUser when LDAP authentication succeeded but the matching local account was never marked as an LDAP user (user.ldap !== true) and the setting LDAP_Merge_Existing_Users is not enabled. Rocket.Chat refuses to silently convert a local password account into an LDAP-backed one, so login fails with Meteor.Error code 'LDAP-login-error'.
Source
Thrown at apps/meteor/server/lib/ldap/Manager.ts:345
): Promise<void> {
logger.debug('running onLDAPLogin');
if (settings.get<boolean>('LDAP_Login_Fallback') && typeof password === 'string' && password.trim() !== '') {
await Accounts.setPasswordAsync(user._id, password, { logout: false });
}
await this.syncUserAvatar(user, ldapUser);
await callbacks.run('onLDAPLogin', { user, ldapUser, isNewUser }, ldap);
}
private static async loginExistingUser(
ldap: LDAPConnection,
user: IUser,
ldapUser: ILDAPEntry,
password?: string,
): Promise<LDAPLoginResult> {
if (user.ldap !== true && settings.get('LDAP_Merge_Existing_Users') !== true) {
logger.debug('User exists without "ldap: true"');
throw new Meteor.Error(
'LDAP-login-error',
`LDAP Authentication succeeded, but there's already an existing user with provided username [${user.username}] in Mongo.`,
);
}
// If we're merging an ldap user with a local user, then we need to sync the data even if 'update data on login' is off.
const forceUserSync = !user.ldap;
const syncData = forceUserSync || (settings.get<boolean>('LDAP_Update_Data_On_Login') ?? true);
logger.debug({ msg: 'Logging user in', syncData });
const updatedUser = (syncData && (await this.syncUserForLogin(ldapUser, user))) || user;
await this.onLogin(ldapUser, updatedUser, password, ldap, false);
return {
userId: user._id,
};
}
View on GitHub (pinned to b2c16d5842)
Solutions
- Enable Admin -> LDAP -> Advanced -> 'Merge existing users' (LDAP_Merge_Existing_Users = true) so the existing account is adopted and flagged as ldap on next login
- Alternatively rename or delete the conflicting local account so the LDAP user is created fresh
- As the affected user, keep using local credentials until an admin resolves the collision
Example fix
// before — default settings LDAP_Merge_Existing_Users = false // local user 'jane' blocks LDAP login for 'jane' // after Admin -> LDAP -> Advanced -> Merge existing users = true // next LDAP login syncs and flags the account; or rename the local account first
Defensive patterns
Strategy: try-catch
Validate before calling
// server-side pre-check before enabling LDAP for a workspace with local accounts
if (settings.get<boolean>('LDAP_Merge_Existing_Users') !== true) {
// warn: any username existing as a non-LDAP local account will fail LDAP login
} Try / catch
try {
const result = await ldapLogin(username, password);
} catch (err) {
if (err instanceof Meteor.Error && err.error === 'LDAP-login-error') {
// LDAP bind succeeded but a local (non-ldap) account owns this username:
// enable Admin -> LDAP -> 'Merge existing users', or rename/remove the local account
}
throw err;
} Prevention
- Enable LDAP_Merge_Existing_Users before announcing SSO login to users who have local accounts
- Audit usernames that exist both locally and in LDAP before cutover (users list vs directory export)
- Provision pre-existing users with ldap: true when they are known to be directory-backed
When it happens
Trigger: An employee first signs in via LDAP (SSO) using a username that already exists as a local account created earlier by registration, admin provisioning, or migration; their document lacks ldap: true and Admin -> LDAP -> 'Merge existing users' is off, so loginExistingUser throws after the bind succeeds.
Common situations: Companies rolling out LDAP/SAML after running Rocket.Chat with local accounts; provisioning scripts that pre-create accounts without the ldap flag; test users created manually before SSO was enabled; same username in both systems by coincidence.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- error-invalid-user
- error-invalid-user
- error-login-blocked-for-ip
- error-login-blocked-for-user
- error-app-user-is-not-allowed-to-login
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/9b68a25534368eba.
Report an issue: GitHub.