{"record":{"id":"9c1a92388033831c","repo":"infiniflow/ragflow","slug":"more-than-one-user-with-username-username-foun","errorCode":null,"errorMessage":"More than one user with username '{username}' found!","messagePattern":"More than one user with username '(.+?)' found!","errorType":"http","errorClass":"AdminException","httpStatus":400,"severity":"critical","filePath":"admin/server/services.py","lineNumber":163,"sourceCode":"        if not target_status:\n            raise AdminException(f\"Invalid activate_status: {activate_status}\")\n        if target_status == usr.is_active:\n            return f\"User activate status is already {_activate_status}!\"\n        # update is_active\n        update_dict = {\"is_active\": target_status}\n        if target_status == ActiveEnum.INACTIVE.value:\n            update_dict[\"access_token\"] = f\"INVALID_{secrets.token_hex(16)}\"\n        UserService.update_user(usr.id, update_dict)\n        return f\"Turn {_activate_status} user activate status successfully!\"\n\n    @staticmethod\n    def get_user_api_key(username: str) -> list[dict[str, Any]]:\n        # use email to find user. check exist and unique.\n        user_list: list[Any] = UserService.query_user_by_email(username)\n        if not user_list:\n            raise UserNotFoundError(username)\n        elif len(user_list) > 1:\n            raise AdminException(f\"More than one user with username '{username}' found!\")\n\n        usr: Any = user_list[0]\n        # tenant_id is typically the same as user_id for the owner tenant\n        tenant_id: str = usr.id\n\n        # Query all API keys for this tenant\n        api_keys: Any = APITokenService.query(tenant_id=tenant_id)\n\n        result: list[dict[str, Any]] = []\n        for key in api_keys:\n            result.append(key.to_dict())\n\n        return result\n\n    @staticmethod\n    def save_api_key(api_key: dict[str, Any]) -> bool:\n        return APITokenService.save(**api_key)\n","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/admin/server/services.py#L145-L181","documentation":"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.","triggerScenarios":"Duplicate user rows sharing the same email (data import, missing unique constraint, racing SSO provisioning); every key-listing call for that email then fails.","commonSituations":"Databases upgraded without adding the email unique index; merged environments; concurrent first-login provisioning via OIDC creating the account twice.","solutions":["Enumerate duplicates: SELECT id, email, create_date FROM user WHERE email = '<username>';","Keep exactly one row (merge or delete extras).","Add a unique index on email to prevent recurrence.","Retry the key listing after dedup."],"exampleFix":"-- before\nSELECT COUNT(*) FROM user WHERE email='user@example.com';  -- >1\n-- after: dedupe, constrain, retry\nDELETE FROM user WHERE email='user@example.com' AND id NOT IN (SELECT * FROM (SELECT MAX(id) FROM user WHERE email='user@example.com') k);\nALTER TABLE user ADD UNIQUE KEY uq_user_email (email);","handlingStrategy":"validation","validationCode":"from api.db.services import UserService\n\ndef assert_unique_target(email: str) -> None:\n    users = UserService.query_user_by_email(email)\n    if len(users) != 1:\n        raise RuntimeError(f'{email}: {len(users)} rows; tenant_id would be ambiguous')","typeGuard":null,"tryCatchPattern":"from admin.server.exceptions import AdminException\ntry:\n    keys = UserMgr.get_user_api_key(email)\nexcept AdminException as e:\n    if 'More than one user' in e.message:\n        raise RuntimeError('duplicate users; key listing unsafe until deduped') from e\n    raise","preventionTips":["Ensure a unique index on email exists from day one.","Audit for duplicate emails during upgrades and after data imports.","Remember tenant_id derives from user id — ambiguous users make every tenant-scoped admin call unsafe."],"tags":["data-integrity","duplicate-users","admin-api","api-keys"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}