The AgentGraph.__del__ method in src/agent/graph.py uses asyncio.run() to clean up the PostgreSQL connection pool. This crashes every time in Chainlit/uvicorn because asyncio.run() cannot be called when an event loop is already running.
Bug Location
File: src/agent/graph.py
Lines: 28-30
def __del__(self) -> None:
if self.pool:
asyncio.run(self.close_pool()) # CRASH
Error Message
RuntimeError: asyncio.run() cannot be called from a running event loop
Why This Happens
asyncio.run() creates a new event loop — but it fails if one is already running
- Chainlit/uvicorn always have an active event loop — so this always crashes
__del__ is unreliable — Python doesn't guarantee when or if it runs
- During interpreter shutdown — the event loop may already be closed
Impact
| Impact |
Severity |
| Production crashes on server shutdown |
Critical |
| Connection pool leaks if cleanup fails |
High |
| Affects all deployments using PostgreSQL checkpointing |
Critical |
Secondary Issue
The LANGGRAPH_DB_URI is constructed at module import time even when environment variables are None:
LANGGRAPH_DB_URI = f"postgresql://{os.getenv('POSTGRES_USER')}:{os.getenv('POSTGRES_PASSWORD')}@postgres:5432/{os.getenv('POSTGRES_LANGGRAPH_DB')}?sslmode=disable"
This creates a malformed URI like postgresql://None:None@postgres:5432/None?sslmode=disable.
Proposed Solution
- Remove
__del__ — eliminates the crash entirely
- Add async context manager —
__aenter__/__aexit__ for proper cleanup
- Add explicit
close() method — idempotent, safe to call multiple times
- Lazy URI construction — build URI only when needed, with validation
The
AgentGraph.__del__method insrc/agent/graph.pyusesasyncio.run()to clean up the PostgreSQL connection pool. This crashes every time in Chainlit/uvicorn becauseasyncio.run()cannot be called when an event loop is already running.Bug Location
File:
src/agent/graph.pyLines: 28-30
Error Message
Why This Happens
asyncio.run()creates a new event loop — but it fails if one is already running__del__is unreliable — Python doesn't guarantee when or if it runsImpact
Secondary Issue
The
LANGGRAPH_DB_URIis constructed at module import time even when environment variables areNone:This creates a malformed URI like
postgresql://None:None@postgres:5432/None?sslmode=disable.Proposed Solution
__del__— eliminates the crash entirely__aenter__/__aexit__for proper cleanupclose()method — idempotent, safe to call multiple times