odysseus-dev/odysseus · info · HTTPException
No active stream for this session
Error message
No active stream for this session
What it means
GET /api/chat/stream_status/{session_id} returns 404 when the session has neither an entry in _active_streams nor an active detached run in agent_runs. The endpoint is a presence probe: 'detached': true is reported when only the background run exists.
Source
Thrown at routes/chat_routes.py:2432
stopped = agent_runs.stop(session_id, _expected_run_id)
return {"stopped": stopped}
# ------------------------------------------------------------------ #
# GET /api/chat/stream_status — check if a stream is active for a session
# ------------------------------------------------------------------ #
@router.get("/api/chat/stream_status/{session_id}")
async def chat_stream_status(request: Request, session_id: str) -> Dict[str, Any]:
_verify_session_owner(request, session_id)
# A detached run can still be going even if _active_streams was popped;
# report it as active so the client knows to reconnect via /resume.
# Read once via .get() to avoid a KeyError race between the membership
# check and the indexed read if a sibling stream's finally pops the
# entry in between (same pattern _stream_set already uses).
rec = _active_streams.get(session_id)
if rec is None:
if agent_runs.is_active(session_id):
return {"status": "streaming", "detached": True}
raise HTTPException(404, "No active stream for this session")
return rec
# ------------------------------------------------------------------ #
# POST /api/inject_context
# ------------------------------------------------------------------ #
@router.post("/api/inject_context/{session_id}")
async def inject_context(request: Request, session_id: str, context: str = Form(...)) -> Dict[str, str]:
_verify_session_owner(request, session_id)
try:
sess = session_manager.get_session(session_id)
msg = untrusted_context_message("injected research context", f"Research Context: {context}")
sess.add_message(ChatMessage(msg["role"], msg["content"], metadata=msg.get("metadata")))
session_manager.save_sessions()
return {"status": "context_injected"}
except KeyError:
raise HTTPException(404, "Session not found")
# ------------------------------------------------------------------ #View on GitHub (pinned to f9235ebbf1)
Solutions
- Treat this 404 as 'idle' in the client (no stream, no run) rather than as an error
- Stop polling once 404 is returned repeatedly and the UI shows the chat as inactive
- If a run should be active, verify it was started detached and the server wasn't restarted
Example fix
// before
const rec = await fetch(statusUrl).then(r => r.json());
// after
const resp = await fetch(statusUrl);
if (resp.status === 404) { /* session idle: render idle UI */ }
const rec = await resp.json(); Defensive patterns
Strategy: try-catch
Try / catch
const resp = await fetch(statusUrl);
if (resp.status === 404) { renderIdleState(); return; }
const rec = await resp.json(); Prevention
- Model 404 from stream_status as 'idle', not an error
- Back off or stop polling after repeated idle results
When it happens
Trigger: Polling stream status for a session with no open SSE stream and no detached run — idle chats, finished runs whose stream record was popped by the finally block, or never-started sessions.
Common situations: Client status polling loop continuing after a stream ends; reconnect logic probing a chat that was closed; race where the stream record was just popped but no detached run replaced it.
Related errors
- No active run for this session
- Session {session_id} not found
- Session '{session}' not found
- str(e)
- Session not found
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/3ee11ad615ed0f45.
Report an issue: GitHub.