theonedev/onedev · error · AuthenticationException
Email address "{0}" already used by another account
Error message
Email address "{0}" already used by another account What it means
When logging in with an external password authenticator, OneDev syncs the authenticated email address to the local user. If that email already exists in the system on a DIFFERENT user and is verified, binding it would hijack the other account, so authentication fails with an AuthenticationException. Unverified emails on other accounts do not block the login.
Source
Thrown at server-core/src/main/java/io/onedev/server/security/DefaultAuthenticatingService.java:158
user = userService.findByName(userName);
if (user != null) {
if (user.isDisabled())
throw new DisabledAccountException(_T("Account is disabled"));
else if (user.getType() != ORDINARY)
throw new DisabledAccountException(_T("Service or AI account not allowed to login"));
if (user.getPassword() == null) {
var authenticator = settingService.getAuthenticator();
if (authenticator != null) {
var authenticated = authenticator.authenticate((UsernamePasswordToken) token);
var emailAddressValue = authenticated.getEmail();
if (emailAddressValue != null) {
var emailAddress = emailAddressService.findByValue(emailAddressValue);
if (emailAddress != null) {
if (emailAddress.getOwner().equals(user) || !emailAddress.isVerified()) {
updateUser(user, authenticated, emailAddress, authenticator.getDefaultGroup());
return user;
} else {
throw new AuthenticationException(MessageFormat.format(_T("Email address \"{0}\" already used by another account"), emailAddressValue));
}
} else {
updateUser(user, authenticated, null, authenticator.getDefaultGroup());
return user;
}
} else {
updateUser(user, authenticated, null, authenticator.getDefaultGroup());
return user;
}
} else {
throw new AuthenticationException(MessageFormat.format(_T("No external password authenticator to authenticate user \"{0}\""), userName));
}
} else {
return user;
}
} else {
var authenticator = settingService.getAuthenticator();
if (authenticator != null) {View on GitHub (pinned to d44925c47c)
Solutions
- Find the OneDev account that owns the verified email (Administration -> Users, search the email) and merge/delete the stale account.
- Correct the email in the external authenticator/LDAP so each account has a unique verified address.
- If the existing verified email is on the wrong account, an admin can remove that email from the other user so it can be claimed.
- Re-attempt login after the duplicate is resolved.
Example fix
// before: LDAP returns jdoe@corp.com for both old and new accounts -> conflict // after (admin): delete stale account or its verified email jdoe@corp.com, // then login succeeds and the email binds to the authenticating user
Defensive patterns
Strategy: try-catch
Validate before calling
// Before mapping SSO emails, ensure uniqueness in the directory: // ldapsearch '(mail=jdoe@corp.com)' uid | ensure exactly one entry
Type guard
function emailIsAvailable(email, users) {
return !users.some(u => u.emails.some(e => e.value === email && e.verified && u.id !== currentUser.id));
} Try / catch
try {
authenticateViaExternal(name, password);
} catch (AuthenticationException e) {
if (e.getMessage().startsWith("Email address")) {
requestAdminMerge(conflictingEmail);
}
} Prevention
- Enforce unique emails in LDAP/SSO directory hygiene.
- Run periodic duplicate-email audits across OneDev accounts.
- Merge/deprovision stale accounts during offboarding instead of leaving verified emails behind.
When it happens
Trigger: External authenticator (SSO/LDAP etc.) returns authenticated.getEmail() whose value matches an existing verified EmailAddress owned by a different user; thrown from updateUser path in doGetAuthenticationInfo.
Common situations: Two directory entries share an email; a user's email was reused for a new employee in LDAP while an old OneDev account still holds the verified address; migrations where the same person has two local accounts.
Related errors
- Email address "{0}" used by account "{1}"
- Unable to change password as you are authenticating via exte
- Unable to find SSO provider:
- Email address "{0}" used by disabled account "{1}"
- Authentication required
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/c2b41c1ca93f1ec3.
Report an issue: GitHub.