langgenius/dify · error · EmailCodeError

email_code_error

email_code_error

Error message

Email code is invalid or expired.

What it means

Raised by POST /console/api/email-code-login/validity (HTTP 400, code email_code_error) when the token is valid and the email matches, but token_data['code'] != req_data.code. The one-time code submitted by the user does not equal the code stored in the token data.

Source

Thrown at api/controllers/console/auth/login.py:303

        original_email = req_data.email
        user_email = original_email.lower()
        language = req_data.language

        token_data = AccountService.get_email_code_login_data(req_data.token)
        if token_data is None:
            _log_console_login_failure(email=user_email, reason=LoginFailureReason.INVALID_EMAIL_CODE_TOKEN)
            raise InvalidTokenError()

        token_email = token_data.get("email")
        normalized_token_email = token_email.lower() if isinstance(token_email, str) else token_email
        if normalized_token_email != user_email:
            _log_console_login_failure(email=user_email, reason=LoginFailureReason.EMAIL_CODE_EMAIL_MISMATCH)
            raise InvalidEmailError()

        if token_data["code"] != req_data.code:
            _log_console_login_failure(email=user_email, reason=LoginFailureReason.INVALID_EMAIL_CODE)
            raise EmailCodeError()

        AccountService.revoke_email_code_login_token(req_data.token)
        try:
            account = _get_account_with_case_fallback(original_email)
        except Unauthorized as exc:
            _log_console_login_failure(email=user_email, reason=LoginFailureReason.ACCOUNT_BANNED)
            raise AccountBannedError() from exc
        except AccountRegisterError:
            _log_console_login_failure(email=user_email, reason=LoginFailureReason.ACCOUNT_IN_FREEZE)
            raise AccountInFreezeError()
        if account:
            tenants = TenantService.get_join_tenants(account, session=db.session())
            if not tenants:
                workspaces = FeatureService.get_license().workspaces
                if not workspaces.is_available():
                    raise WorkspacesLimitExceeded()
                if not FeatureService.is_workspace_creation_allowed():
                    raise NotAllowedCreateWorkspace()

View on GitHub (pinned to ef8544b173)

Solutions

  1. Request and enter a fresh code, typing carefully.
  2. Verify the client encrypts the code the same way @decrypt_code_field expects (check RSA public key / encryption scheme).
  3. Make sure the user is reading the most recent email, not an older one.
  4. If the code is correct but still rejected, confirm the token has not already been consumed by a concurrent validity call.

Example fix

// before
fetch('/console/api/email-code-login/validity', {body: JSON.stringify({email, code: rawCode, token})})
// after - encrypt the code field to match @decrypt_code_field
const encryptedCode = await encryptWithPublicKey(serverPublicKey, rawCode)
fetch('/console/api/email-code-login/validity', {body: JSON.stringify({email, code: encryptedCode, token})})
Defensive patterns

Strategy: validation

Validate before calling

# Validate the code format before submitting and ensure it is encrypted
if not code or not code.isdigit() or len(code) != EXPECTED_CODE_LEN:
    show_error('Enter the full numeric code from the email.')
    return
encrypted_code = encrypt_for_server(code)
submit_validity(email, encrypted_code, token)

Type guard

null

Try / catch

from controllers.console.auth.error import EmailCodeError
try:
    verify_code(email, code, token)
except EmailCodeError:
    prompt('The code is wrong; request a new one if unsure.')

Prevention

When it happens

Trigger: POST /console/api/email-code-login/validity with a wrong, mistyped, or expired-but-still-present code. The token data is intact, the email matches, but the code field differs.

Common situations: User mistyped the numeric code; code from a previous email; OCR/copy error; client applied the wrong code transformation (e.g., the @decrypt_code_field decorator expects an encrypted code that the client sent in plaintext or vice-versa).

Related errors


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