infiniflow/ragflow · critical · AdminException

More than one user with username '{username}' found!

Error message

More than one user with username '{username}' found!

What it means

AdminException (HTTP 400) raised by UserMgr.get_user_api_key (admin/server/services.py:163) with the message "More than one user with username '{username}' found!" when the email matches multiple rows. Since tenant_id is taken from user_list[0].id, an ambiguous match would list the wrong tenant's keys, so it is refused.

Source

Thrown at admin/server/services.py:163

        if not target_status:
            raise AdminException(f"Invalid activate_status: {activate_status}")
        if target_status == usr.is_active:
            return f"User activate status is already {_activate_status}!"
        # update is_active
        update_dict = {"is_active": target_status}
        if target_status == ActiveEnum.INACTIVE.value:
            update_dict["access_token"] = f"INVALID_{secrets.token_hex(16)}"
        UserService.update_user(usr.id, update_dict)
        return f"Turn {_activate_status} user activate status successfully!"

    @staticmethod
    def get_user_api_key(username: str) -> list[dict[str, Any]]:
        # use email to find user. check exist and unique.
        user_list: list[Any] = UserService.query_user_by_email(username)
        if not user_list:
            raise UserNotFoundError(username)
        elif len(user_list) > 1:
            raise AdminException(f"More than one user with username '{username}' found!")

        usr: Any = user_list[0]
        # tenant_id is typically the same as user_id for the owner tenant
        tenant_id: str = usr.id

        # Query all API keys for this tenant
        api_keys: Any = APITokenService.query(tenant_id=tenant_id)

        result: list[dict[str, Any]] = []
        for key in api_keys:
            result.append(key.to_dict())

        return result

    @staticmethod
    def save_api_key(api_key: dict[str, Any]) -> bool:
        return APITokenService.save(**api_key)

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Enumerate duplicates: SELECT id, email, create_date FROM user WHERE email = '<username>';
  2. Keep exactly one row (merge or delete extras).
  3. Add a unique index on email to prevent recurrence.
  4. Retry the key listing after dedup.

Example fix

-- before
SELECT COUNT(*) FROM user WHERE email='user@example.com';  -- >1
-- after: dedupe, constrain, retry
DELETE FROM user WHERE email='user@example.com' AND id NOT IN (SELECT * FROM (SELECT MAX(id) FROM user WHERE email='user@example.com') k);
ALTER TABLE user ADD UNIQUE KEY uq_user_email (email);
Defensive patterns

Strategy: validation

Validate before calling

from api.db.services import UserService

def assert_unique_target(email: str) -> None:
    users = UserService.query_user_by_email(email)
    if len(users) != 1:
        raise RuntimeError(f'{email}: {len(users)} rows; tenant_id would be ambiguous')

Try / catch

from admin.server.exceptions import AdminException
try:
    keys = UserMgr.get_user_api_key(email)
except AdminException as e:
    if 'More than one user' in e.message:
        raise RuntimeError('duplicate users; key listing unsafe until deduped') from e
    raise

Prevention

When it happens

Trigger: Duplicate user rows sharing the same email (data import, missing unique constraint, racing SSO provisioning); every key-listing call for that email then fails.

Common situations: Databases upgraded without adding the email unique index; merged environments; concurrent first-login provisioning via OIDC creating the account twice.

Related errors


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