{"record":{"id":"8d5421881ff42f2e","repo":"langgenius/dify","slug":"password-mismatch","errorCode":"password_mismatch","errorMessage":"The passwords do not match.","messagePattern":"The passwords do not match\\.","errorType":"error_code","errorClass":"PasswordMismatchError","httpStatus":400,"severity":"error","filePath":"api/controllers/console/auth/email_register.py","lineNumber":166,"sourceCode":"        )\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\n    @console_ns.expect(console_ns.models[EmailRegisterResetPayload.__name__])\n    @console_ns.response(200, \"Success\", console_ns.models[EmailRegisterResetResponse.__name__])\n    @model_validate(EmailRegisterResetPayload)\n    def post(self, req_data: EmailRegisterResetPayload):\n\n        # Validate passwords match\n        if req_data.new_password != req_data.password_confirm:\n            raise PasswordMismatchError()\n\n        # Validate token and get register data\n        register_data = AccountService.get_email_register_data(req_data.token)\n        if not register_data:\n            raise InvalidTokenError()\n        # Must use token in reset phase\n        if register_data.get(\"phase\", \"\") != \"register\":\n            raise InvalidTokenError()\n\n        # Revoke token to prevent reuse\n        AccountService.revoke_email_register_token(req_data.token)\n\n        email = register_data.get(\"email\", \"\")\n        normalized_email = email.lower()\n\n        account = AccountService.get_account_by_email_with_case_fallback(email, session=db.session())\n\n        if account:","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/controllers/console/auth/email_register.py#L148-L184","documentation":"Raised by PasswordMismatchError in EmailRegisterResetApi.post before any token work happens. The payload fields new_password and password_confirm are compared directly; if they differ, registration aborts. This is the only guard that fires before the token is looked up, so it reveals nothing about token state.","triggerScenarios":"POST /console/api/email-register with new_password != password_confirm in the JSON body. Pure client-side validation moved server-side as a safety net.","commonSituations":"Password manager autofills one field but not the other; caps-lock or different keyboard layout; user retypes differently in the confirm box; frontend skips its own equality check.","solutions":["Compare the two password fields in the UI before submitting and disable the submit button until they match.","Show a real-time 'passwords do not match' indicator under the confirm field.","Clear and re-type both fields rather than patching one character.","Ensure the form sends both fields from the same source values, not two independent inputs."],"exampleFix":"// before\n<button disabled={!password}>Sign up</button>\n// after\ndisabled={password !== confirm || !password}","handlingStrategy":"validation","validationCode":"if (newPassword !== passwordConfirm) {\n  setFieldError('password_confirm', 'Passwords do not match');\n  return;\n}","typeGuard":"function passwordsMatch(a, b) { return typeof a === 'string' && a === b && a.length > 0; }","tryCatchPattern":null,"preventionTips":["Disable submit until both fields are non-empty and equal.","Show a real-time match indicator.","Send both fields from the same React state value."],"tags":["auth","registration","validation","password"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}