langgenius/dify · warning · EmailRegisterLimitError
email_register_limit
email_register_limit
Error message
Too many failed email register attempts. Please try again in 24 hours.
What it means
Raised by EmailRegisterLimitError in EmailRegisterCheckApi.post when AccountService.is_email_register_error_rate_limit returns true. The rate limiter accumulates failures from bad verification codes (see add_email_register_error_rate_limit) and blocks the email for 24 hours once the threshold is crossed. This protects the code-verification step from brute-forcing.
Source
Thrown at api/controllers/console/auth/email_register.py:126
token = AccountService.send_email_register_email(email=normalized_email, account=account, language=language)
return {"result": "success", "data": token}
@console_ns.route("/email-register/validity")
class EmailRegisterCheckApi(Resource):
@setup_required
@email_password_login_enabled
@email_register_enabled
@console_ns.expect(console_ns.models[EmailRegisterValidityPayload.__name__])
@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)
View on GitHub (pinned to ef8544b173)
Solutions
- Stop retrying and wait 24 hours for the limit to expire, or have a privileged flow reset_email_register_error_rate_limit(email).
- Request a fresh registration email and enter the code carefully on the first attempt.
- If writing tests, mock AccountService.is_email_register_error_rate_limit to return false, or use a unique email per test.
- Surface the 'email_register_limit' code to the user as a cooldown message, not a hard failure.
Example fix
// before
const res = await checkValidity({ email, token, code });
// after: respect the cooldown
if (res.status === 400 && body.code === 'email_register_limit') {
showCooldownUntil(tomorrow());
return;
} Defensive patterns
Strategy: try-catch
Try / catch
try {
await checkValidity({ email, token, code });
} catch (e) {
if (e.code === 'email_register_limit') showCooldown(24 * 3600);
else if (e.code === 'email_code_error') bumpAttemptCounter();
else throw e;
} Prevention
- Show a live attempt counter so the user knows how close they are to the limit.
- Throttle code-entry retries client-side (e.g., exponential backoff after each failure).
- Mock is_email_register_error_rate_limit in tests to avoid accidental lockouts.
When it happens
Trigger: POST /console/api/email-register/validity with an email that has produced too many failed code validations within the rate-limit window. Triggered before the token is even examined.
Common situations: User mistypes the email verification code repeatedly; automated tests hammering the validity endpoint; a script trying to guess codes. Resets only via reset_email_register_error_rate_limit after a successful validation.
Related errors
- email_send_ip_limit
- account_in_freeze
- email_code_error
- email_password_reset_limit
- invalid_or_expired_token
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/e8acce5e5dbd0c48.
Report an issue: GitHub.