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

  1. Find the OneDev account that owns the verified email (Administration -> Users, search the email) and merge/delete the stale account.
  2. Correct the email in the external authenticator/LDAP so each account has a unique verified address.
  3. 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.
  4. 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

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


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/c2b41c1ca93f1ec3. Report an issue: GitHub.