From c406aede962ccdb4d21621963b698e35f27fdc18 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Fri, 27 Jun 2025 08:57:35 -0700 Subject: [PATCH] Fix deadlock in SqliteStore - If setup wasnt called separately _cursor() and setup() would deadlock - The call to setup() in _cursor() should be outside the lock block, as setup() also acquires the lock and re-checks the setup flag --- libs/checkpoint-sqlite/langgraph/store/sqlite/aio.py | 5 ++--- libs/checkpoint-sqlite/langgraph/store/sqlite/base.py | 9 ++++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/libs/checkpoint-sqlite/langgraph/store/sqlite/aio.py b/libs/checkpoint-sqlite/langgraph/store/sqlite/aio.py index 3b19e512d..6be00813b 100644 --- a/libs/checkpoint-sqlite/langgraph/store/sqlite/aio.py +++ b/libs/checkpoint-sqlite/langgraph/store/sqlite/aio.py @@ -223,10 +223,9 @@ class AsyncSqliteStore(AsyncBatchedBaseStore, BaseSqliteStore): Yields: An SQLite cursor object. """ + if not self.is_setup: + await self.setup() async with self.lock: - if not self.is_setup: - await self.setup() - if transaction: await self.conn.execute("BEGIN") diff --git a/libs/checkpoint-sqlite/langgraph/store/sqlite/base.py b/libs/checkpoint-sqlite/langgraph/store/sqlite/base.py index 5ac1ee0e0..db161d667 100644 --- a/libs/checkpoint-sqlite/langgraph/store/sqlite/base.py +++ b/libs/checkpoint-sqlite/langgraph/store/sqlite/base.py @@ -981,10 +981,9 @@ class SqliteStore(BaseSqliteStore, BaseStore): Args: transaction (bool): whether to use transaction for the DB operations """ + if not self.is_setup: + self.setup() with self.lock: - if not self.is_setup: - self.setup() - if transaction: self.conn.execute("BEGIN") @@ -1002,10 +1001,10 @@ class SqliteStore(BaseSqliteStore, BaseStore): This method creates the necessary tables in the SQLite database if they don't already exist and runs database migrations. It should be called before first use. """ - if self.is_setup: - return with self.lock: + if self.is_setup: + return # Create migrations table if it doesn't exist self.conn.executescript( """