You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Stop mid-stream then edit + resend → 409 'session already has an active stream', resent message never appears #10
Reported by a community member in the Hermes #android-app Discord (2026-07-09). Thanks for the report, and thanks @ComputerByte for looking at it live in-channel.
Symptom
Start a generation (agent begins streaming a reply).
Hit Stop / cancel mid-stream.
Edit the prompt and re-send it.
→ The app returns an error that the request is "already in stream", and the newly edited/resent message never appears in the conversation.
What this maps to server-side
The "already in stream" wording is a paraphrase of the Bridge API's real response. The server returns HTTP 409 with {"error": "session already has an active stream"} from POST /api/chat/start when the session still has a live/owned stream. So the API is deliberately rejecting the resend — this is a real 409, not a cosmetic client string.
Edit-and-resend is a truncate-then-resend against the API: POST /api/session/truncate followed by POST /api/chat/start. If that chat/start reaches the server while the prior turn's stream is still considered active, the 409 is the correct response.
Two candidate root causes — how to tell which
A) Client sequencing (most likely, this repo). If the native edit+resend fires chat/startbeforePOST /api/chat/cancel?stream_id=<id> is issued, or before the cancel actually lands, the old stream legitimately still owns the session and the server correctly 409s. Fix would be to make edit+resend await a successful cancel (and let the old SSE tear down) before issuing the new chat/start — i.e. serialize stop → cancel-confirmed → truncate → start.
B) Server-side unwind-window race (possible — escalate to nesquena/hermes-webui if you confirm this). On the server, cancel_stream() clears session.active_stream_idbefore the worker thread fully exits, but the run stays in ACTIVE_RUNS during a bounded post-cancel unwind window (see _active_run_stream_for_session, ref #3808). A chat/start that arrives inside that window can be blocked even though the user did cancel first. If you observe the 409 after a chat/cancel that returned {"ok": true, "cancelled": true}, that points here, and it's a WebUI-side issue — please open an issue on nesquena/hermes-webui with the request timeline and I'll take it.
Suggested diagnostic
Capture the exact request order + responses around the repro:
Did the client send POST /api/chat/cancel?stream_id=<id>? What did it return?
How long between the cancel response and the chat/start that got the 409?
Was active_stream_id in the chat/start 409 body the old stream id?
That timeline cleanly separates A (no/late cancel → client fix) from B (cancel confirmed, still 409 → server fix).
WebUI 409 source: api/routes.py — _start_agent_turn active-stream guard ("session already has an active stream"), the /api/chat/cancel handler, and _active_stream_blocks_chat_start / _active_run_stream_for_session (post-cancel unwind window, #3808).
Filed from the Hermes WebUI triage side; happy to take the server half if the timeline shows case B.
Activity
release: v0.12.2-preview issue #10 hotfix