WS heartbeats create rogue conversations from empty messages #31

Closed
opened 2026-07-28 05:07:13 -07:00 by westfarn · 0 comments
Owner

Problem

Prod showed rogue conversations with titles like Please Provide Your First Message. I'll Generate A, tied to long-lived LLM work.

Root cause: the frontend WebSocket keepalive sends { "type": "ping", "email": ... } with no message or conversation_id. Both chat consumers treated that as a new chat:

  1. Call title generator on empty/null text
  2. Create a conversation
  3. Run the full LLM pipeline

An idle tab (e.g. mobile viewport left open) heartbeats every ~25s and can spawn these repeatedly.

Frontend already guards empty prompt text in the form, but the backend did not reject empty/whitespace payloads, and heartbeats were not ignored.

Expected

  • type: ping frames are ignored (no conversation, no title LLM, no chat pipeline)
  • Empty / whitespace-only user messages are rejected before any DB or LLM work
  • REST prompt create path also rejects empty text

Scope

  • Backend: consumers.py, consumers_graph.py, PromptSerializer, ConversationDetailView
  • Frontend defense-in-depth (trim + sendMessage guard) may land in chat_web_app separately if needed

Acceptance

  • Ping heartbeats create zero conversations
  • Empty/whitespace WS payloads return an error and create nothing
  • PromptSerializer rejects blank/whitespace messages
  • Tests cover heartbeat ignore + empty-message rejection
## Problem Prod showed rogue conversations with titles like `Please Provide Your First Message. I'll Generate A`, tied to long-lived LLM work. Root cause: the frontend WebSocket keepalive sends `{ "type": "ping", "email": ... }` with **no** `message` or `conversation_id`. Both chat consumers treated that as a new chat: 1. Call title generator on empty/null text 2. Create a conversation 3. Run the full LLM pipeline An idle tab (e.g. mobile viewport left open) heartbeats every ~25s and can spawn these repeatedly. Frontend already guards empty prompt text in the form, but the backend did not reject empty/whitespace payloads, and heartbeats were not ignored. ## Expected - `type: ping` frames are ignored (no conversation, no title LLM, no chat pipeline) - Empty / whitespace-only user messages are rejected before any DB or LLM work - REST prompt create path also rejects empty text ## Scope - Backend: `consumers.py`, `consumers_graph.py`, `PromptSerializer`, `ConversationDetailView` - Frontend defense-in-depth (trim + `sendMessage` guard) may land in `chat_web_app` separately if needed ## Acceptance - [ ] Ping heartbeats create zero conversations - [ ] Empty/whitespace WS payloads return an error and create nothing - [ ] `PromptSerializer` rejects blank/whitespace messages - [ ] Tests cover heartbeat ignore + empty-message rejection
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ai_ml_operations/chat_backend#31