From eae429b3bd2c50cfa62f9444a0e5c07e8b53aeef Mon Sep 17 00:00:00 2001 From: Nikita Date: Fri, 6 Feb 2026 21:55:05 +0300 Subject: [PATCH] fix: complete SqliteSaver async compatibility in chat routers (#525) * fix: use sync get_state() for SqliteSaver in chat routers Replace async aget_state() calls with sync get_state() wrapped in asyncio.to_thread() to fix SqliteSaver compatibility issues. SqliteSaver does not support async methods, so we need to run the sync version in a separate thread. This is a follow-up to #519 which fixed the same issue in graph_utils.py but missed four locations: - chat.py: get_session() and execute_chat() - source_chat.py: get_source_chat_session() and stream_source_chat_response() Co-Authored-By: Claude Opus 4.5 * chore: translate comments to English --------- Co-authored-by: Claude Opus 4.5 Co-authored-by: Luis Novo --- api/routers/chat.py | 12 ++++++++---- api/routers/source_chat.py | 12 ++++++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/api/routers/chat.py b/api/routers/chat.py index f4523be..8abe669 100644 --- a/api/routers/chat.py +++ b/api/routers/chat.py @@ -190,8 +190,10 @@ async def get_session(session_id: str): raise HTTPException(status_code=404, detail="Session not found") # Get session state from LangGraph to retrieve messages - thread_state = await chat_graph.aget_state( - config=RunnableConfig(configurable={"thread_id": full_session_id}) + # Use sync get_state() in a thread since SqliteSaver doesn't support async + thread_state = await asyncio.to_thread( + chat_graph.get_state, + config=RunnableConfig(configurable={"thread_id": full_session_id}), ) # Extract messages from state @@ -348,8 +350,10 @@ async def execute_chat(request: ExecuteChatRequest): ) # Get current state - current_state = await chat_graph.aget_state( - config=RunnableConfig(configurable={"thread_id": full_session_id}) + # Use sync get_state() in a thread since SqliteSaver doesn't support async + current_state = await asyncio.to_thread( + chat_graph.get_state, + config=RunnableConfig(configurable={"thread_id": full_session_id}), ) # Prepare state for execution diff --git a/api/routers/source_chat.py b/api/routers/source_chat.py index 779657b..9b7fa20 100644 --- a/api/routers/source_chat.py +++ b/api/routers/source_chat.py @@ -231,8 +231,10 @@ async def get_source_chat_session( ) # Get session state from LangGraph to retrieve messages - thread_state = await source_chat_graph.aget_state( - config=RunnableConfig(configurable={"thread_id": full_session_id}) + # Use sync get_state() in a thread since SqliteSaver doesn't support async + thread_state = await asyncio.to_thread( + source_chat_graph.get_state, + config=RunnableConfig(configurable={"thread_id": full_session_id}), ) # Extract messages from state @@ -416,8 +418,10 @@ async def stream_source_chat_response( """Stream the source chat response as Server-Sent Events.""" try: # Get current state - current_state = await source_chat_graph.aget_state( - config=RunnableConfig(configurable={"thread_id": session_id}) + # Use sync get_state() in a thread since SqliteSaver doesn't support async + current_state = await asyncio.to_thread( + source_chat_graph.get_state, + config=RunnableConfig(configurable={"thread_id": session_id}), ) # Prepare state for execution