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
- Fetch the current session list and use a valid ID, or create a new session
- Handle 404 on stream open by resetting the client's session state instead of retrying
- 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
- Refresh session IDs on reconnect/restart
- Treat 404 mid-conversation as 'start a new session', never a blind retry
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
- Session not found
- Session not found
- Session {session_id} not found
- Integration not found
- Calendar not found
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/9ece76679be2dce2.
Report an issue: GitHub.