infiniflow/ragflow · critical · AdminException

Can't init admin.

Error message

Can't init admin.

What it means

Raised during admin server bootstrap (admin/server/auth.py:102) when no superuser exists in the user table and UserService.save() of the hard-coded default admin (admin@ragflow.io / base64('admin')) returns falsy — i.e. the INSERT failed at the database layer. It aborts server startup because the system cannot guarantee an administrative account exists. The AdminException carries HTTP 500.

Source

Thrown at admin/server/auth.py:102

        else:
            return None


def init_default_admin():
    # Verify that at least one active admin user exists. If not, create a default one.
    users = UserService.query(is_superuser=True)
    if not users:
        default_admin = {
            "id": uuid.uuid1().hex,
            "password": encode_to_base64("admin"),
            "nickname": "admin",
            "is_superuser": True,
            "email": "admin@ragflow.io",
            "creator": "system",
            "status": "1",
        }
        if not UserService.save(**default_admin):
            raise AdminException("Can't init admin.", 500)
        add_tenant_for_admin(default_admin, UserTenantRole.OWNER)
    elif not any([u.is_active == ActiveEnum.ACTIVE.value for u in users]):
        raise AdminException("No active admin. Please update 'is_active' in db manually.", 500)
    else:
        default_admin_rows = [u for u in users if u.email == "admin@ragflow.io"]
        if default_admin_rows:
            default_admin = default_admin_rows[0].to_dict()
            exist, default_admin_tenant = TenantService.get_by_id(default_admin["id"])
            if not exist:
                add_tenant_for_admin(default_admin, UserTenantRole.OWNER)


def add_tenant_for_admin(user_info: dict, role: str):

    tenant = {
        "id": user_info["id"],
        "name": user_info["nickname"] + "‘s Kingdom",
        "llm_id": settings.CHAT_MDL,

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Check the metadata DB is reachable and migrations are applied (the user table exists and matches current models) before starting the admin server.
  2. Inspect server logs immediately above this raise — Peewee logs the underlying DB error that made UserService.save fail.
  3. If a conflicting/partial admin row exists, delete or repair it in the user table so the bootstrap insert can succeed on restart.
  4. Restart the admin server after fixing the DB; bootstrap is idempotent (it only inserts when no superuser exists).
Defensive patterns

Strategy: validation

Validate before calling

from api.db.services import UserService
from common.constants import ActiveEnum
users = UserService.query(is_superuser=True)
if not users:
    # bootstrap insert will run; verify DB writability first
    probe = UserService.save(id="probe", email="probe@invalid")  # only in a sandbox
    assert probe, "user table not writable; fix DB before starting admin server"

Try / catch

from api.common.exceptions import AdminException
try:
    init_admin()  # auth bootstrap
except AdminException as e:
    if "Can't init admin" in str(e):
        # inspect DB connectivity/migrations before restart
        raise

Prevention

When it happens

Trigger: First boot of the admin server (or a wipe of the user table) against a broken database: MySQL/Postgres unreachable mid-init, schema not migrated (table missing), a column constraint violation on the insert, or duplicate id/email causing the save to fail. UserService.save returning None/False on any DB error maps directly to this raise.

Common situations: Running the admin server before applying DB migrations or before docker-compose-base services (MySQL) are healthy; pointing SAUTH/DB env vars at a stale database that already has a conflicting admin@ragflow.io row; schema drift after upgrading RAGFlow without running the migration scripts.

Related errors


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