odysseus-dev/odysseus · error · HTTPException

Session not found

Error message

Session not found

What it means

HTTP 404 from POST /v1/chat when resuming a session: session_manager.get_session(session_id) raised (KeyError or any Exception). The broad except (KeyError, Exception) intentionally converts every lookup failure — unknown id, expired/purged session, corrupted session store — into the same 404 so it does not leak internals.

Source

Thrown at routes/webhook/webhook_routes.py:262

        token_owner = getattr(request.state, "api_token_owner", None)

        from core.models import ChatMessage
        from src.llm_core import llm_call_async
        from src.endpoint_resolver import build_chat_url, build_headers, build_models_url, normalize_base

        message = body.message.strip()
        if not message:
            raise HTTPException(400, "Message is required")

        session_id = body.session
        sess = None

        # --- Case 1: Resume an existing session ---
        if session_id and session_manager:
            try:
                sess = session_manager.get_session(session_id)
            except (KeyError, Exception):
                raise HTTPException(404, "Session not found")
            # SECURITY: verify the API-token's user owns this session — without
            # this any token holder could resume any user's chat by passing its
            # ID. The token's user is on request.state.user (set by API-token
            # middleware); fall back to require_user if not present.
            try:
                from src.auth_helpers import get_current_user as _gcu
                _tok_user = token_owner or getattr(request.state, "user", None) or _gcu(request)
            except Exception:
                _tok_user = None
            # Strict ownership (see _caller_owns_session): fail closed so a
            # null-owner / cross-owner session can't be resumed by an arbitrary
            # chat-scoped token.
            _sess_owner = getattr(sess, "owner", None)
            if not _caller_owns_session(_sess_owner, _tok_user):
                raise HTTPException(404, "Session not found")

        # --- Case 2: Direct API key + model (no pre-configured endpoint needed) ---
        if not sess and body.api_key:

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Start a fresh conversation by omitting body.session, capture the new session id from the response, and store that
  2. Verify the session exists (GET session endpoint / admin UI) before reusing it
  3. Ensure session persistence is enabled so ids survive restarts
Defensive patterns

Strategy: fallback

Try / catch

if resp.status_code == 404 and 'Session not found' in detail:
    resp = chat(message=body.message, api_key=..., model=...)  # fresh session, no `session` field
    store_new_session_id(resp["session"])

Prevention

When it happens

Trigger: Passing a session id that never existed, was deleted, or was lost when the process restarted and sessions were not persisted/loaded; a session id from a different deployment.

Common situations: Automation retrying an old conversation after server restart without saved sessions; long-lived n8n workflows storing session ids past their retention; typo'd/truncated UUID.

Related errors


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