From ac00d40e3633e04a2e3ed21441fe125db9424845 Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Fri, 25 Sep 2026 07:06:56 +0200 Subject: [PATCH] fix: model sync no longer fails with "database is locked" on SQLite (#31349) On the default SQLite setup (session sharing off), a POST to /api/v1/models/sync containing any model that already exists answered 200 with an empty list and stored nothing. After a 5 second stall, the only trace was "database is locked" in the server log. The sync wrote each model's access grants while the model update was still uncommitted. Without session sharing the grant writes run on a second database session, and SQLite allows one writer at a time, so that write waited on the same request's uncommitted update until the busy timeout expired and the whole sync was dropped. Grants are now written after the model changes are committed, the same order model create and update already use. A failed model commit now also leaves every grant untouched. PostgreSQL and setups with session sharing on behave as before. Fixes #31346 --- backend/open_webui/models/models.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/backend/open_webui/models/models.py b/backend/open_webui/models/models.py index 00a7a2650e..8da346ab70 100755 --- a/backend/open_webui/models/models.py +++ b/backend/open_webui/models/models.py @@ -622,16 +622,20 @@ class ModelsTable: await db.execute(update(Model).filter_by(id=model.id).values(**model_data)) else: db.add(Model(**model_data)) - await AccessGrants.set_access_grants('model', model.id, model.access_grants, db=db) # Remove models that are no longer present for model in existing_models: if model.id not in new_model_ids: - await AccessGrants.revoke_all_access('model', model.id, db=db) await db.delete(model) await db.commit() + # Grants after the commit to avoid SQLite write-lock contention when session sharing is off + for model in models: + await AccessGrants.set_access_grants('model', model.id, model.access_grants, db=db) + for model_id in existing_ids - new_model_ids: + await AccessGrants.revoke_all_access('model', model_id, db=db) + result = await db.execute(select(Model)) all_models = result.scalars().all() model_ids = [model.id for model in all_models]