SqliteStore._cursor hangs indefinitely due to deadlock when not set up #727

Closed
opened 2026-02-20 17:41:28 -05:00 by yindo · 1 comment
Owner

Originally created by @2wiceUponATime on GitHub (Jun 20, 2025).

Checked other resources

  • This is a bug, not a usage question. For questions, please use GitHub Discussions.
  • I added a clear and detailed title that summarizes the issue.
  • I read what a minimal reproducible example is (https://stackoverflow.com/help/minimal-reproducible-example).
  • I included a self-contained, minimal example that demonstrates the issue INCLUDING all the relevant imports. The code run AS IS to reproduce the issue.

Example Code

# Requires langgraph-checkpoint-sqlite
from langgraph.store.sqlite import SqliteStore

with SqliteStore.from_conn_string(":memory:") as store:
  # Any method that calls self._cursor will never return
  store.search(("foo",))

Error Message and Stack Trace (if applicable)


Description

I'm trying to create long-term memory storage with SqliteStore from langgraph-checkpoint-sqlite (langgraph.store.sqlite). If I try to search the store before the SQLite tables are set up, I expect an empty list of results. Instead, SqliteStore.search hangs indefinitely. This is due to the following code in base.py:

    @contextmanager
    def _cursor(self, *, transaction: bool = True) -> Iterator[sqlite3.Cursor]:
        """Create a database cursor as a context manager.

        Args:
            transaction (bool): whether to use transaction for the DB operations
        """
        with self.lock:
            if not self.is_setup:
                self.setup()

            # ...

    def setup(self) -> None:
        """Set up the store database.

        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:
            # ...

            self.is_setup = True

First, _cursor locks self.lock. If self.is_setup is false, _cursor will call setup. setup also tries to acquire the lock, but it is already taken by _cursor, causing a deadlock. Possible fixes:

  • Change SqliteStore.lock from threading.Lock to threading.RLock.
  • Move the setup code inside with self.lock: to an internal method like _setup, which both _cursor and setup can call.
  • Temporary fix for langgraph-checkpoint-sqlite users: Call setup after initializing a SqliteStore and before calling any methods that query the database.

A similar issue occurs with AsyncSqliteStore.

System Info

System Information

OS: Windows
OS Version: 10.0.26100
Python Version: 3.13.5 (tags/v3.13.5:6cb20a2, Jun 11 2025, 16:15:46) [MSC v.1943 64 bit (AMD64)]

Package Information

langchain_core: 0.3.65
langsmith: 0.3.45

Optional packages not installed

langserve

Other Dependencies

httpx: 0.28.1
jsonpatch<2.0,>=1.33: Installed. No version info available.
langsmith-pyo3: Installed. No version info available.
langsmith<0.4,>=0.3.45: Installed. No version info available.
openai-agents: Installed. No version info available.
opentelemetry-api: Installed. No version info available.
opentelemetry-exporter-otlp-proto-http: Installed. No version info available.
opentelemetry-sdk: Installed. No version info available.
orjson: 3.10.18
packaging: 24.2
packaging<25,>=23.2: Installed. No version info available.
pydantic: 2.11.7
pydantic>=2.7.4: Installed. No version info available.
pytest: Installed. No version info available.
PyYAML>=5.3: Installed. No version info available.
requests: 2.32.4
requests-toolbelt: 1.0.0
rich: Installed. No version info available.
tenacity!=8.4.0,<10.0.0,>=8.1.0: Installed. No version info available.
typing-extensions>=4.7: Installed. No version info available.
zstandard: 0.23.0

Originally created by @2wiceUponATime on GitHub (Jun 20, 2025). ### Checked other resources - [x] This is a bug, not a usage question. For questions, please use GitHub Discussions. - [x] I added a clear and detailed title that summarizes the issue. - [x] I read what a minimal reproducible example is (https://stackoverflow.com/help/minimal-reproducible-example). - [x] I included a self-contained, minimal example that demonstrates the issue INCLUDING all the relevant imports. The code run AS IS to reproduce the issue. ### Example Code ```python # Requires langgraph-checkpoint-sqlite from langgraph.store.sqlite import SqliteStore with SqliteStore.from_conn_string(":memory:") as store: # Any method that calls self._cursor will never return store.search(("foo",)) ``` ### Error Message and Stack Trace (if applicable) ```shell ``` ### Description I'm trying to create long-term memory storage with SqliteStore from langgraph-checkpoint-sqlite (langgraph.store.sqlite). If I try to search the store before the SQLite tables are set up, I expect an empty list of results. Instead, `SqliteStore.search` hangs indefinitely. This is due to the following code in [`base.py`](https://github.com/langchain-ai/langgraph/blob/eba18c32136373590598ab6dba9e38b9138d41bc/libs/checkpoint-sqlite/langgraph/store/sqlite/base.py#L978): ```python @contextmanager def _cursor(self, *, transaction: bool = True) -> Iterator[sqlite3.Cursor]: """Create a database cursor as a context manager. Args: transaction (bool): whether to use transaction for the DB operations """ with self.lock: if not self.is_setup: self.setup() # ... def setup(self) -> None: """Set up the store database. 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: # ... self.is_setup = True ``` First, `_cursor` locks `self.lock`. If `self.is_setup` is false, `_cursor` will call `setup`. `setup` also tries to acquire the lock, but it is already taken by `_cursor`, causing a deadlock. Possible fixes: * Change `SqliteStore.lock` from `threading.Lock` to `threading.RLock`. * Move the `setup` code inside `with self.lock:` to an internal method like `_setup`, which both `_cursor` and `setup` can call. * Temporary fix for `langgraph-checkpoint-sqlite` users: Call `setup` after initializing a `SqliteStore` and before calling any methods that query the database. A similar issue occurs with `AsyncSqliteStore`. ### System Info System Information ------------------ > OS: Windows > OS Version: 10.0.26100 > Python Version: 3.13.5 (tags/v3.13.5:6cb20a2, Jun 11 2025, 16:15:46) [MSC v.1943 64 bit (AMD64)] Package Information ------------------- > langchain_core: 0.3.65 > langsmith: 0.3.45 Optional packages not installed ------------------------------- > langserve Other Dependencies ------------------ > httpx: 0.28.1 > jsonpatch<2.0,>=1.33: Installed. No version info available. > langsmith-pyo3: Installed. No version info available. > langsmith<0.4,>=0.3.45: Installed. No version info available. > openai-agents: Installed. No version info available. > opentelemetry-api: Installed. No version info available. > opentelemetry-exporter-otlp-proto-http: Installed. No version info available. > opentelemetry-sdk: Installed. No version info available. > orjson: 3.10.18 > packaging: 24.2 > packaging<25,>=23.2: Installed. No version info available. > pydantic: 2.11.7 > pydantic>=2.7.4: Installed. No version info available. > pytest: Installed. No version info available. > PyYAML>=5.3: Installed. No version info available. > requests: 2.32.4 > requests-toolbelt: 1.0.0 > rich: Installed. No version info available. > tenacity!=8.4.0,<10.0.0,>=8.1.0: Installed. No version info available. > typing-extensions>=4.7: Installed. No version info available. > zstandard: 0.23.0
yindo added the bug label 2026-02-20 17:41:28 -05:00
yindo closed this issue 2026-02-20 17:41:28 -05:00
Author
Owner

@sydney-runkle commented on GitHub (Jun 27, 2025):

Looks like a bug, thanks for the report! We'll fix soon.

@sydney-runkle commented on GitHub (Jun 27, 2025): Looks like a bug, thanks for the report! We'll fix soon.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/langgraph#727