{"record":{"id":"52a4ade4ef737bfc","repo":"langgenius/dify","slug":"email-code-error","errorCode":"email_code_error","errorMessage":"Email code is invalid or expired.","messagePattern":"Email code is invalid or expired\\.","errorType":"error_code","errorClass":"EmailCodeError","httpStatus":400,"severity":"error","filePath":"api/controllers/console/auth/email_register.py","lineNumber":140,"sourceCode":"        user_email = req_data.email.lower()\n\n        is_email_register_error_rate_limit = AccountService.is_email_register_error_rate_limit(user_email)\n        if is_email_register_error_rate_limit:\n            raise EmailRegisterLimitError()\n\n        token_data = AccountService.get_email_register_data(req_data.token)\n        if token_data is None:\n            raise InvalidTokenError()\n\n        token_email = token_data.get(\"email\")\n        normalized_token_email = token_email.lower() if isinstance(token_email, str) else token_email\n\n        if user_email != normalized_token_email:\n            raise InvalidEmailError()\n\n        if req_data.code != token_data.get(\"code\"):\n            AccountService.add_email_register_error_rate_limit(user_email)\n            raise EmailCodeError()\n\n        # Verified, revoke the first token\n        AccountService.revoke_email_register_token(req_data.token)\n\n        # Refresh token data by generating a new token\n        _, new_token = AccountService.generate_email_register_token(\n            user_email, code=req_data.code, additional_data={\"phase\": \"register\"}\n        )\n\n        AccountService.reset_email_register_error_rate_limit(user_email)\n        return {\"is_valid\": True, \"email\": normalized_token_email, \"token\": new_token}\n\n\n@console_ns.route(\"/email-register\")\nclass EmailRegisterResetApi(Resource):\n    @setup_required\n    @email_password_login_enabled\n    @email_register_enabled","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/controllers/console/auth/email_register.py#L122-L158","documentation":"Raised by EmailCodeError in EmailRegisterCheckApi.post when req_data.code does not equal the code stored in the registration token. Each failure increments the error-rate-limit counter via add_email_register_error_rate_limit, eventually producing error 401. The code is a short numeric/alphanumeric pin delivered by email.","triggerScenarios":"POST /console/api/email-register/validity with a wrong, expired, already-consumed, or typo'd verification code while the token and email are valid.","commonSituations":"User mistypes the 6-digit code; code from a previous email is used after a resend; OCR misreads the code; user pastes with leading/trailing whitespace.","solutions":["Trim whitespace and re-enter the code from the most recent registration email.","If unsure, request a new code via email-send and use the new token+code pair together.","Track attempts client-side and warn the user before they hit the rate-limit threshold.","Verify the code input has no thousands separators or formatting inserted by autofill."],"exampleFix":"// before\ncheckValidity({ email, token, code: rawInput });\n// after: normalize and pair with the latest token\ncheckValidity({ email, token: latestToken, code: rawInput.trim() });","handlingStrategy":"validation","validationCode":"const cleanCode = String(code).trim();\nif (!/^\\d{4,8}$/.test(cleanCode)) {\n  warnInvalidCodeFormat();\n  return;\n}","typeGuard":"function looksLikeVerificationCode(c) { return typeof c === 'string' && /^\\d{4,8}$/.test(c.trim()); }","tryCatchPattern":"try {\n  await checkValidity({ email, token, code: cleanCode });\n} catch (e) {\n  if (e.code === 'email_code_error') bumpAttempts();\n  else if (e.code === 'email_register_limit') showCooldown();\n  else throw e;\n}","preventionTips":["Trim and validate code format client-side before sending.","Use the code from the most recent email only.","Disable autofill on the code input."],"tags":["auth","registration","verification-code","brute-force-protection"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}