diff --git a/src/agentkit/server/auth/models.py b/src/agentkit/server/auth/models.py index 3ced901..b958044 100644 --- a/src/agentkit/server/auth/models.py +++ b/src/agentkit/server/auth/models.py @@ -749,6 +749,9 @@ async def init_auth_db(db_path: str | Path | None = None) -> Path: async with aiosqlite.connect(str(path)) as db: db.row_factory = aiosqlite.Row await db.execute("PRAGMA journal_mode=WAL") + # Set busy_timeout to prevent "database is locked" errors on + # concurrent writes (waits up to 5 seconds before failing). + await db.execute("PRAGMA busy_timeout = 5000") await db.executescript(_SCHEMA_SQL) # Record the current schema version (idempotent upsert). diff --git a/src/agentkit/server/routes/admin.py b/src/agentkit/server/routes/admin.py index 284fb11..924fe52 100644 --- a/src/agentkit/server/routes/admin.py +++ b/src/agentkit/server/routes/admin.py @@ -65,10 +65,16 @@ def _resolve_db_path(request: Request) -> Path: async def _ensure_db(request: Request) -> Path: - """Ensure the auth DB exists; returns the resolved path.""" + """Ensure the auth DB schema is up to date; returns the resolved path. + + Always calls ``init_auth_db`` (idempotent) to ensure all tables + exist and pending migrations are applied — even when the DB file + already exists. This fixes the issue where existing V2 DBs were + never migrated to V3/V4 because the ``if not db_path.exists()`` + guard skipped ``init_auth_db`` (U5/R8). + """ db_path = _resolve_db_path(request) - if not db_path.exists(): - await init_auth_db(db_path) + await init_auth_db(db_path) return db_path