langgenius/dify · error · InvalidEmailError

invalid_email

invalid_email

Error message

The email address is not valid.

What it means

Raised by InvalidEmailError in EmailRegisterCheckApi.post when the lowercased email in the request body does not match the email bound to the registration token. The token was issued for one address; the client is now claiming a different one. This guards against token/email substitution mid-flow.

Source

Thrown at api/controllers/console/auth/email_register.py:136

    @console_ns.response(200, "Success", console_ns.models[VerificationTokenResponse.__name__])
    @model_validate(EmailRegisterValidityPayload)
    def post(self, req_data: EmailRegisterValidityPayload):

        user_email = req_data.email.lower()

        is_email_register_error_rate_limit = AccountService.is_email_register_error_rate_limit(user_email)
        if is_email_register_error_rate_limit:
            raise EmailRegisterLimitError()

        token_data = AccountService.get_email_register_data(req_data.token)
        if token_data is None:
            raise InvalidTokenError()

        token_email = token_data.get("email")
        normalized_token_email = token_email.lower() if isinstance(token_email, str) else token_email

        if user_email != normalized_token_email:
            raise InvalidEmailError()

        if req_data.code != token_data.get("code"):
            AccountService.add_email_register_error_rate_limit(user_email)
            raise EmailCodeError()

        # Verified, revoke the first token
        AccountService.revoke_email_register_token(req_data.token)

        # Refresh token data by generating a new token
        _, new_token = AccountService.generate_email_register_token(
            user_email, code=req_data.code, additional_data={"phase": "register"}
        )

        AccountService.reset_email_register_error_rate_limit(user_email)
        return {"is_valid": True, "email": normalized_token_email, "token": new_token}


@console_ns.route("/email-register")

View on GitHub (pinned to ef8544b173)

Solutions

  1. Use the exact email address that received the registration link, character-for-character.
  2. Pull email from the same client state that received the token, not from a re-typed input.
  3. Normalize both sides to lowercase before comparing client-side as a sanity check.
  4. If the wrong email was registered, restart email-send with the correct address.

Example fix

// before
checkValidity({ email: typedEmail, token, code });
// after: derive email from the token-issuing flow
checkValidity({ email: issuedToEmail.toLowerCase(), token, code });
Defensive patterns

Strategy: validation

Validate before calling

// Derive email from the same state that holds the token
const emailForCheck = issuedToEmail.toLowerCase();
if (emailForCheck !== userInputEmail.toLowerCase()) {
  warnEmailMismatch();
  return;
}

Try / catch

try {
  await checkValidity({ email: emailForCheck, token, code });
} catch (e) {
  if (e.code === 'invalid_email') showEmailMismatchHint();
  else throw e;
}

Prevention

When it happens

Trigger: POST /console/api/email-register/validity where the token's stored email differs from req_data.email (after both are lowercased). Common when a user starts registration with one address and types another at verification, or when the client passes the wrong email field.

Common situations: Plus-addressing differences (user+test@x vs user@x), autocorrect changing the address between steps, shared browser where two users mix up tabs, or a frontend bug sending stale email state.

Related errors


AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12). Data as JSON: /api/errors/fdfa514e8cbc02d3. Report an issue: GitHub.