langchain-ai / langchain-ai/langgraph

[Bug]: Potential sqlite3.OperationalError database is locked during highly concurrent aput operations

Open
#8,136 8 comments 0 reactions 0 assignees View on GitHub
bug external
Dominant language
Python
Stars
41.8k
Forks
7.1k
Avg merge
23h 7m
Merged PRs (30d)
30

Description

### Checked other resources

- [x] This is a bug, not a usage question.
- [x] I added a clear and descriptive title that summarizes this issue.
- [x] I used the GitHub search to find a similar question and didn't find it.
- [x] I am sure that this is a bug in LangGraph rather than my code.
- [x] The bug is not resolved by updating to the latest stable version of LangGraph (or the specific integration package).
- [x] This is not related to the langchain-community package.
- [x] I posted a self-contained, minimal, reproducible example. A maintainer can copy it and run it AS IS.

### Related Issues / PRs

None

### Reproduction Steps / Example Code (Python)

```python
import asyncio
from langchain_core.runnables import RunnableConfig
from langgraph.checkpoint.base import Checkpoint, CheckpointMetadata
from langgraph.checkpoint.sqlite.aio import AsyncSqliteSaver

async def simulate_concurrent_writes():
# Initialize the checkpointer in memory
async with AsyncSqliteSaver.from_conn_string(":memory:") as saver:
await saver.setup()

# Prepare mock checkpoint data
config: RunnableConfig = {"configurable": {"thread_id": "test_thread", "checkpoint_ns": ""}}
checkpoint: Checkpoint = {"v": 1, "id": "1", "ts": "2026-01-01T00:00:00Z", "channel_values": {}, "channel_versions": {}, "versions_seen": {}}
metadata: CheckpointMetadata = {"source": "input", "step": 1, "writes": {}}
new_versions = {}

# Worker simulating concurrent agent writes
async def worker(worker_id):
cfg = config.copy()
cfg["configurable"] = config["configurable"].copy()
cfg["configurable"]["checkpoint_id"] = f"check_{worker_id}"
await saver.aput(cfg, checkpoint, metadata, new_versions)

# Trigger 50 concurrent writes at the exact same time
# Without BEGIN IMMEDIATE, this highly concurrent scenario can expose
# the database to "sqlite3.OperationalError: database is locked"
tasks = [worker(i) for i in range(50)]
await asyncio.gather(*tasks)

if __name__ == "__main__":
asyncio.run(simulate_concurrent_writes())
```

### Error Message and Stack Trace (if applicable)

```shell

```

### Description

### Description
In high-concurrency environments, when multiple async agents attempt to write checkpoints simultaneously using `AsyncSqliteSaver.aput`, SQLite can occasionally fail with a `sqlite3.OperationalError: database is locked`.

### Proposed Fix
Enforcing a `BEGIN IMMEDIATE` transaction block within the `async with self.lock` section inside `langgraph/checkpoint/sqlite/aio.py` ensures that SQLite acquires a write lock before executing the statement, preventing concurrent write collisions.

### System Info

System Information
------------------
> OS: Windows
> OS Version: 10.0.26200
> Python Version: 3.11.9 (tags/v3.11.9:de54cf5, Apr 2 2024, 10:12:12) [MSC v.1938 64 bit (AMD64)]

Package Information
-------------------
> langchain_core: 1.4.7
> langsmith: 0.8.16
> langchain_protocol: 0.0.17

Optional packages not installed
-------------------------------
> deepagents
> deepagents-cli

Other Dependencies
------------------
> httpx: 0.28.1
> jsonpatch: 1.33
> orjson: 3.11.9
> packaging: 26.2
> pydantic: 2.13.4
> pyyaml: 6.0.3
> requests: 2.32.3
> requests-toolbelt: 1.0.0
> rich: 15.0.0
> tenacity: 9.1.4
> typing-extensions: 4.15.0
> uuid-utils: 0.16.2
> websockets: 15.0
> wrapt: 2.2.1
> xxhash: 3.7.0
> zstandard: 0.25.0

Contributor guide

Open the contributing guide

Research direction

Start in langgraph/checkpoint/sqlite/aio.py, focusing on AsyncSqliteSaver.aput and the async lock section described in the issue. Run the provided 50-worker reproduction with AsyncSqliteSaver.from_conn_string(":memory:") and verify that concurrent writes complete without sqlite3.OperationalError: database is locked.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, sqlite
Domain
databases
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.