odysseus-dev/odysseus · error · HTTPException

str(e)

Error message

str(e)

What it means

During the streaming send's request-shaping phase, session resolution raised SessionNotFoundError (distinct from a plain KeyError) and the handler surfaces its message verbatim as a 404. This typically comes from coerce_message_and_session or later session loads when the requested session does not exist.

Source

Thrown at routes/chat_routes.py:1103

                )
            if isinstance(message, str) and _is_contextual_browser_followup(message, sess):
                _explicit_browser_intent = True
                if chat_mode == "chat":
                    chat_mode = "agent"
                    auto_escalated = True
                    _workspace_agent_intent = False
                    logger.info("chat→agent auto-escalation: contextual browser/form follow-up")
            if not workspace and isinstance(message, str):
                _auto_workspace, _ = _resolve_workspace_from_message_path(request, message)
                if _auto_workspace:
                    workspace = _auto_workspace
                    chat_mode = "agent"
                    auto_escalated = True
                    _workspace_agent_intent = True
                    allow_bash = "true"
                    logger.info("chat→agent auto-escalation: explicit path workspace=%s", workspace)
        except SessionNotFoundError as e:
            raise HTTPException(404, str(e))
        except (ValueError, ValidationError):
            raise HTTPException(400, "Invalid request parameters")

        # ------------------------------------------------------------------ #
        # Privilege gates that must fire BEFORE any LLM work / token spend.
        #   1. allowed_models — reject if session.model isn't in the user's
        #      configured allowlist (empty list = "no restriction").
        #   2. max_messages_per_day — count user-role ChatMessage rows owned
        #      by this user in the last UTC day; 429 if at/over the cap.
        # Admins always have full privileges via get_privileges (returns
        # ADMIN_PRIVILEGES wholesale) so this is a no-op for them.
        _enforce_chat_privileges(request, sess)

        # Ensure session has auth headers
        resolve_session_auth(sess, session, owner=effective_user(request))

        # Check for research_pending BEFORE mode persist overwrites it
        do_research = str(use_research).lower() == "true"

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Fetch the current session list and use a valid ID, or create a new session
  2. Handle 404 on stream open by resetting the client's session state instead of retrying
  3. Check server logs for concurrent deletion if the ID was recently valid
Defensive patterns

Strategy: fallback

Validate before calling

const exists = await fetch(`/api/sessions/${sessionId}/exists`).then(r=>r.ok);
if (!exists) sessionId = await createSession();

Try / catch

try { await streamChat(sessionId, ...); }
catch (e) { if (e.status === 404) { sessionId = await createSession(); await streamChat(sessionId, ...); } else throw e; }

Prevention

When it happens

Trigger: POST /api/chat_stream with a session ID that is absent from the session manager at the coercion/loading step — deleted sessions, stale IDs after restart, or IDs the caller does not own.

Common situations: Client cached an old session ID; session deleted in another tab; server restarted with in-memory session state; concurrent delete-while-sending races.

Related errors


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