infiniflow/ragflow · error · AdminException

Email and password do not match!

Error message

Email and password do not match!

What it means

AdminException raised in login_admin (admin/server/auth.py:163) when the email exists but UserService.query_user(email, decrypt(password)) returns nothing — the RSA-decrypted, base64-decoded password does not match the stored one. This is the classic bad-credential error for the admin login endpoint, thrown only after the account lookup succeeded.

Source

Thrown at admin/server/auth.py:163

            raise AdminException(f"User {current_user.email} inactive", 403)

        return func(*args, **kwargs)

    return wrapper


def login_admin(email: str, password: str):
    """
    :param email: admin email
    :param password: string before decrypt (RSA encrypted + base64 encoded)
    """
    users = UserService.query(email=email)
    if not users:
        raise UserNotFoundError(email)
    decrypted = decrypt(password)
    user = UserService.query_user(email, decrypted)
    if not user:
        raise AdminException("Email and password do not match!")
    if not user.is_superuser:
        raise AdminException("Not admin", 403)
    if user.is_active == ActiveEnum.INACTIVE.value:
        raise AdminException(f"User {email} inactive", 403)

    resp = user.to_json()
    user.access_token = get_uuid()
    login_user(user)
    user.update_time = (current_timestamp(),)
    user.update_date = (datetime_format(datetime.now()),)
    user.last_login_time = get_format_time()
    user.save()
    msg = "Welcome back!"
    return sync_construct_response(data=resp, auth=user.get_id(), message=msg)


def check_admin(username: str, password: str):
    users = UserService.query(email=username)

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Retry with the correct password, encrypted exactly like the frontend/ragflow_cli does (RSA encrypt + base64) — see the contract documented in admin/client/user.py.
  2. If locked out, reset the stored hash in the DB to encode_to_base64('admin') to restore the default credential, then change it after login.
  3. Verify you are not hitting /auth/login (regular flow) with admin-flow encrypted credentials or vice versa.

Example fix

-- emergency reset to the default password 'admin' (base64)
UPDATE user SET password = TO_BASE64('admin') WHERE email = 'admin@ragflow.io';
Defensive patterns

Strategy: try-catch

Validate before calling

# verify credentials the same way the server does, without the admin flow
from api.utils.crypt import decrypt
from api.db.services import UserService
if not UserService.query_user(email, decrypt(encrypted_password)):
    raise PermissionError("email/password mismatch; will raise 'Email and password do not match!' on login")

Try / catch

from api.common.exceptions import AdminException
for attempt_credential in candidates:
    try:
        session = login_admin(email, attempt_credential)
        break
    except AdminException as e:
        if "do not match" not in str(e):
            raise  # only retry on bad password, not on Not admin/inactive
else:
    raise RuntimeError("all candidate passwords rejected")

Prevention

When it happens

Trigger: POST /admin/login with the right email and a wrong password; sending a password that was not RSA-encrypted+base64-encoded the way the client/server pair expects (decrypt() yields garbage, so query_user misses); password changed in DB or via UI while an old credential file is still used.

Common situations: Using the default admin/admin after the password was already rotated; scripts that store the plaintext or differently-encoded password; frontend/CLI encryption mismatch after a RAGFlow upgrade changed the RSA key handling in api.utils.crypt.

Related errors


AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15). Data as JSON: /api/errors/bcff3c81df9ed840. Report an issue: GitHub.