odysseus-dev/odysseus · warning · HTTPException

No active run for this session

Error message

No active run for this session

What it means

GET /api/chat/resume/{session_id} found no active detached agent run for that session and returns 404. Resume only works while a background run is registered in agent_runs; once it finishes (or never started), there is nothing to reattach to.

Source

Thrown at routes/chat_routes.py:2399

            return StreamingResponse(_safe_stream(), media_type="text/event-stream")

        _detached_run = agent_runs.start(session, _safe_stream())
        return StreamingResponse(
            agent_runs.subscribe(session, _detached_run),
            media_type="text/event-stream",
            headers={"X-Odysseus-Run-Id": _detached_run.run_id},
        )

    # ------------------------------------------------------------------ #
    # GET /api/chat/resume — reconnect to a detached run that's still going
    # (e.g. after reopening a session whose agent kept running in the background)
    # ------------------------------------------------------------------ #
    @router.get("/api/chat/resume/{session_id}")
    async def chat_resume(request: Request, session_id: str) -> StreamingResponse:
        _verify_session_owner(request, session_id)
        _active_run = agent_runs.get_active_run(session_id)
        if _active_run is None:
            raise HTTPException(404, "No active run for this session")
        return StreamingResponse(
            agent_runs.subscribe(session_id, _active_run),
            media_type="text/event-stream",
            headers={"X-Odysseus-Run-Id": _active_run.run_id},
        )

    # ------------------------------------------------------------------ #
    # POST /api/chat/stop — cancel a detached run (Stop button). Closing the SSE
    # no longer stops it (it's detached), so the Stop button must call this.
    # ------------------------------------------------------------------ #
    @router.post("/api/chat/stop/{session_id}")
    async def chat_stop(request: Request, session_id: str) -> Dict[str, Any]:
        _verify_session_owner(request, session_id)
        _expected_run_id = request.headers.get("X-Odysseus-Run-Id")
        stopped = agent_runs.stop(session_id, _expected_run_id)
        return {"stopped": stopped}

    # ------------------------------------------------------------------ #

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Treat this 404 as 'run finished or absent' — fetch the session's messages normally instead of resuming
  2. Use GET /api/chat/stream_status/{session_id} first to check whether a detached run is active before calling resume
  3. Only call resume when the client previously received a run ID (X-Odysseus-Run-Id header) for an ongoing run

Example fix

// before
const es = new EventSource(`/api/chat/resume/${sessionId}`);
// after
const st = await fetch(`/api/chat/stream_status/${sessionId}`).then(r=>r.json());
const es = st.status === 'streaming'
  ? new EventSource(st.detached ? `/api/chat/resume/${sessionId}` : `/api/chat/stream/${sessionId}`)
  : null; // fall back to loading history
Defensive patterns

Strategy: validation

Validate before calling

const st = await fetch(`/api/chat/stream_status/${sessionId}`).then(r => r.ok ? r.json() : null);
if (st?.status === 'streaming' && st.detached) {
  const es = new EventSource(`/api/chat/resume/${sessionId}`);
} else { loadHistory(sessionId); }

Try / catch

try { await attachResume(sessionId); } catch (e) { if (e.status === 404) await loadHistory(sessionId); else throw e; }

Prevention

When it happens

Trigger: Calling resume after a detached run has completed; calling resume for a session that never had a detached run; calling it after a server restart cleared in-memory run state; racing the run's final moments.

Common situations: Browser reconnects to a session whose agent already finished; user bookmarks/refreshes the resume URL late; client retry logic calling resume in a loop after completion.

Related errors


AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14). Data as JSON: /api/errors/33849d97f39caa55. Report an issue: GitHub.