langgenius/dify · error · PasswordMismatchError

password_mismatch

password_mismatch

Error message

The passwords do not match.

What it means

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.

Solutions

  1. Compare the two password fields in the UI before submitting and disable the submit button until they match.
  2. Show a real-time 'passwords do not match' indicator under the confirm field.
  3. Clear and re-type both fields rather than patching one character.
  4. Ensure the form sends both fields from the same source values, not two independent inputs.

Example fix

// before
<button disabled={!password}>Sign up</button>
// after
disabled={password !== confirm || !password}
Defensive patterns

Strategy: validation

Validate before calling

if (newPassword !== passwordConfirm) {
  setFieldError('password_confirm', 'Passwords do not match');
  return;
}

Type guard

function passwordsMatch(a, b) { return typeof a === 'string' && a === b && a.length > 0; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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

Appendix: source

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

        )

        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")
class EmailRegisterResetApi(Resource):
    @setup_required
    @email_password_login_enabled
    @email_register_enabled
    @console_ns.expect(console_ns.models[EmailRegisterResetPayload.__name__])
    @console_ns.response(200, "Success", console_ns.models[EmailRegisterResetResponse.__name__])
    @model_validate(EmailRegisterResetPayload)
    def post(self, req_data: EmailRegisterResetPayload):

        # Validate passwords match
        if req_data.new_password != req_data.password_confirm:
            raise PasswordMismatchError()

        # Validate token and get register data
        register_data = AccountService.get_email_register_data(req_data.token)
        if not register_data:
            raise InvalidTokenError()
        # Must use token in reset phase
        if register_data.get("phase", "") != "register":
            raise InvalidTokenError()

        # Revoke token to prevent reuse
        AccountService.revoke_email_register_token(req_data.token)

        email = register_data.get("email", "")
        normalized_email = email.lower()

        account = AccountService.get_account_by_email_with_case_fallback(email, session=db.session())

        if account:

View on GitHub (pinned to ef8544b173)