langgenius/dify · error · EmailAlreadyInUseError
email_already_in_use
email_already_in_use
Error message
A user with this email already exists.
What it means
Raised by EmailAlreadyInUseError in EmailRegisterResetApi.post after the token is validated and revoked, when AccountService.get_account_by_email_with_case_fallback finds an existing account for that email. The case-insensitive lookup means differing capitalization does not bypass it. The token has already been revoked at this point, so the flow cannot be retried with the same token.
Source
Thrown at api/controllers/console/auth/email_register.py:185
# Validate token and get register data
register_data = AccountService.get_email_register_data(req_data.token)
if not register_data:
raise InvalidTokenError()
# Must use token in reset phase
if register_data.get("phase", "") != "register":
raise InvalidTokenError()
# Revoke token to prevent reuse
AccountService.revoke_email_register_token(req_data.token)
email = register_data.get("email", "")
normalized_email = email.lower()
account = AccountService.get_account_by_email_with_case_fallback(email, session=db.session())
if account:
raise EmailAlreadyInUseError()
account = self._create_new_account(
email=normalized_email,
password=req_data.password_confirm,
timezone=req_data.timezone,
language=req_data.language,
)
token_pair = AccountService.login(account=account, session=db.session(), ip_address=extract_remote_ip(request))
AccountService.reset_login_error_rate_limit(normalized_email)
return {"result": "success", "data": token_pair.model_dump()}
def _create_new_account(
self,
email: str,
password: str,
timezone: str | None = None,
language: str | None = None,View on GitHub (pinned to ef8544b173)
Solutions
- If the user owns the account, direct them to login or forgot-password instead of registration.
- Restart email-send only if the email genuinely should be new; otherwise the account exists.
- Add a pre-check (e.g., an existence probe) before starting registration to fail fast.
- Handle the 'email_already_in_use' code in the UI with a link to the login flow.
Example fix
// before
register({ token, ... }); // user already has account
// after
if (res.code === 'email_already_in_use') {
router.push('/signin?email=' + encodeURIComponent(email));
} Defensive patterns
Strategy: try-catch
Validate before calling
// Optional pre-check if an existence probe exists; otherwise rely on try-catch
if (await accountExists(email)) {
redirect('/signin?email=' + encodeURIComponent(email));
return;
} Try / catch
try {
await register({ token, ... });
} catch (e) {
if (e.code === 'email_already_in_use') redirect('/signin');
else throw e;
} Prevention
- Offer a 'sign in instead' link when registration detects an existing account.
- Avoid concurrent registration tabs for the same email.
- Remember prior successful registrations to short-circuit.
When it happens
Trigger: POST /console/api/email-register where an account already exists for the email (case-insensitive). The user completed verification but the email was registered by someone else (or themselves in another session) in the meantime.
Common situations: Two browser tabs both registering; user forgot they already have an account; race between concurrent registrations; email alias that case-folds onto an existing account; previous failed registration that actually created the account.
Related errors
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/ba778d80c01f3240.
Report an issue: GitHub.