Skip to content

[BUG] Messages without session_id are attached to the oldest existing chat session instead of the active one #822

Description

@Ryzen-Starbit

Description of the Bug

In backend/app/routes/chat.py, _save_message() falls back to an unordered .first() query when session_id is not supplied:

if not session_id:
    session = db.query(ChatSession).filter(
        ChatSession.user_id == user_id
    ).first()   # no order_by

Once any session exists, .first() deterministically keeps returning the OLDEST session (not the most recent, not one scoped to the current document), so every fallback-triggered message keeps piling into that same original session going forward.

This fallback is reachable in real, non-contrived flows:

  1. A brand-new user's very first message. ChatRequest.session_id is Optional (schemas.py), and frontend/src/store/chat-store.ts only auto-selects an existing session in fetchSessions() - there's nothing to select before any session exists, so the first question a new user asks (a completely normal flow - open a doc, start typing) is sent with session_id: null.
  2. Any transient failure of GET /chat/sessions. The catch block in fetchSessions() unconditionally resets activeSessionId to null:
    } catch (err) {
    set({ sessions: [], activeSessionId: null });
    }
    This fires on any network blip or backend hiccup while fetching sessions - even for a returning user with an established, valid active session - and silently reroutes their next message away from their real conversation.

The dedicated "New Chat" flow (ChatSessionSidebar.tsx -> createSession()) is unaffected, since it always creates a real session via POST /chat/sessions before use.

Steps to Reproduce

  1. Register a new account (zero existing chat sessions).
  2. Upload a document and immediately ask a question without pressing "New Chat" first.
  3. Ask a question about a second, unrelated document the same way.
  4. Call GET /chat/sessions - both conversations are merged into a single "Default Chat" session instead of being scoped separately.

Alternative repro for trigger path 2:

  1. As an existing user with an active session, block/fail the GET /api/v1/chat/sessions request (devtools network throttling or temporarily stopping the backend during that call).
  2. Ask a question.
  3. Observe it lands in the oldest session, not the one you were just in.

Expected Behavior

When no session_id is supplied, the backend should create a fresh session scoped to the current context (or the frontend should create one via
POST /chat/sessions before sending the first message), rather than silently reusing an unrelated pre-existing session via an unordered .first() query.

Screenshots / Logs

PS C:\Users\ankit\OneDrive\Desktop\work\Projects\PDF-Assistant-RAG> Get-ChildItem backend/app -Recurse -File | Select-String -Pattern "_save_message" | Format-Table Path, LineNumber, Line

Path LineNumber Line


C:\Users\ankit\OneDrive\Desktop\work\Projects\PDF-Assistant-RAG\backend\app\routes\chat.py 181 _sav...
C:\Users\ankit\OneDrive\Desktop\work\Projects\PDF-Assistant-RAG\backend\app\routes\chat.py 672 _sav...
C:\Users\ankit\OneDrive\Desktop\work\Projects\PDF-Assistant-RAG\backend\app\routes\chat.py 673 _sav...
C:\Users\ankit\OneDrive\Desktop\work\Projects\PDF-Assistant-RAG\backend\app\routes\chat.py 802 _save_me...
C:\Users\ankit\OneDrive\Desktop\work\Projects\PDF-Assistant-RAG\backend\app\routes\chat.py 871 ...
C:\Users\ankit\OneDrive\Desktop\work\Projects\PDF-Assistant-RAG\backend\app\routes\chat.py 1086 def _save_me...

PS C:\Users\ankit\OneDrive\Desktop\work\Projects\PDF-Assistant-RAG> Get-ChildItem frontend/src -Recurse -File | Select-String -Pattern "activeSessionId"

frontend\src\components\chat\ChatPanel.tsx:86: const activeSessionId = useChatStore((state) =>
state.activeSessionId);
frontend\src\components\chat\ChatPanel.tsx:163: // Load history on activeSessionId or fallback to activeDoc change
frontend\src\components\chat\ChatPanel.tsx:165: if (activeSessionId) {
frontend\src\components\chat\ChatPanel.tsx:166: fetchSessionHistory(activeSessionId);
frontend\src\components\chat\ChatPanel.tsx:212: }, [activeSessionId, activeDoc, fetchSessionHistory, setMessages]);
frontend\src\components\chat\ChatPanel.tsx:277: session_id: activeSessionId,
frontend\src\components\chat\ChatPanel.tsx:404: session_id: activeSessionId,
frontend\src\components\chat\ChatSessionSidebar.tsx:12: const activeSessionId = useChatStore((state) =>
state.activeSessionId);
frontend\src\components\chat\ChatSessionSidebar.tsx:17: const setActiveSessionId = useChatStore((state) =>
state.setActiveSessionId);
frontend\src\components\chat\ChatSessionSidebar.tsx:79: setActiveSessionId(id);
frontend\src\components\chat\ChatSessionSidebar.tsx:130: const isActive = session.id === activeSessionId;
frontend\src\store\chat-store.ts:50: activeSessionId: string | null;
frontend\src\store\chat-store.ts:61: setActiveSessionId: (value: Setter<string | null>) => void;
frontend\src\store\chat-store.ts:80: activeSessionId: null,
frontend\src\store\chat-store.ts:109: setActiveSessionId(value) {
frontend\src\store\chat-store.ts:111: activeSessionId: resolveValue(value, state.activeSessionId),
frontend\src\store\chat-store.ts:125: if (data.length > 0 && !get().activeSessionId) {
frontend\src\store\chat-store.ts:126: set({ activeSessionId: data[0].id });
frontend\src\store\chat-store.ts:135: activeSessionId: null,
frontend\src\store\chat-store.ts:147: activeSessionId: session.id,
frontend\src\store\chat-store.ts:177: let nextActiveId = state.activeSessionId;
frontend\src\store\chat-store.ts:178: if (state.activeSessionId === id) {
frontend\src\store\chat-store.ts:183: activeSessionId: nextActiveId,
frontend\src\store\chat-store.ts:186: const activeId = get().activeSessionId;
frontend\src\store\chat-store.ts:220: activeSessionId: null,

PS C:\Users\ankit\OneDrive\Desktop\work\Projects\PDF-Assistant-RAG>

Environment

Windows 11

GSSoC '26

  • Yes, I am participating in GirlScript Summer of Code and would like to fix this.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workinggssocGirlScript Summer of Code 2026 issue/PR

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions