odysseus-dev/odysseus · error · HTTPException
Session '{session}' not found
Error message
Session '{session}' not found What it means
The non-streaming chat endpoint could not find the given session ID in the session manager after ownership verification passed. get_session raises KeyError for unknown IDs, which the handler maps to a 404. Ownership is checked first, so a foreign session also surfaces as this 404 rather than a 403.
Source
Thrown at routes/chat_routes.py:697
async def chat_endpoint(request: Request, chat_request: ChatRequest) -> Dict[str, Any]:
_set_user_time_from_request(request)
message = chat_request.message
session = chat_request.session
att_ids = chat_request.attachments or []
use_web = chat_request.use_web
use_research = chat_request.use_research
time_filter = chat_request.time_filter
preset_id = chat_request.preset_id
# Verify the caller owns this session before loading it.
# Without this, any authenticated user can post into another user's chat.
_verify_session_owner(request, session)
try:
sess = session_manager.get_session(session)
except KeyError:
raise HTTPException(404, f"Session '{session}' not found")
owner = effective_user(request)
if _clear_orphaned_session_endpoint(sess, owner=owner):
raise HTTPException(400, "Selected model endpoint was removed. Pick another model in Settings.")
# Empty model + live endpoint = setup race (Issue #587). Repair from
# the endpoint's cached model list before privilege checks, which
# otherwise see "" and behave inconsistently with the allowlist.
_recover_empty_session_model(sess, session, owner=owner)
if not getattr(sess, "model", "").strip():
raise HTTPException(
400,
"No model selected for this chat. Open the model picker and choose one before sending.",
)
if not (getattr(sess, "endpoint_url", "") or "").strip():
raise HTTPException(400, "Selected model endpoint is not configured")
# Same allowed_models + daily-cap gate as chat_stream (mirror so the
# non-streaming path can't be used to bypass).View on GitHub (pinned to f9235ebbf1)
Solutions
- List sessions via the sessions API and use a current, owned session ID
- Create a new session when the client gets this 404 instead of retrying the same ID
- If sessions should survive restarts, verify session persistence/save is functioning
Example fix
// before
fetch(`/api/chat/${sessionId}`, {method:'POST', body})
// after
const r = await fetch(`/api/chat/${sessionId}`, {method:'POST', body});
if (r.status === 404) { sessionId = await createNewSession(); /* retry once */ } Defensive patterns
Strategy: fallback
Validate before calling
const sessions = await fetch('/api/sessions').then(r=>r.json());
const ok = sessions.some(s => s.id === sessionId);
if (!ok) sessionId = await createSession(); Try / catch
try { await postChat(sessionId, body); }
catch (e) { if (e.status === 404 && /not found/.test(e.message)) { sessionId = await createSession(); await postChat(sessionId, body); } else throw e; } Prevention
- Reconcile the client's session list on app start
- Treat session 404 as a reset signal: create fresh, drop the stale ID
When it happens
Trigger: POST to the non-streaming chat route with a session ID that was deleted, never existed, or belongs to another user (cross-user IDs are masked as 404).
Common situations: Client kept a stale session ID after server restart cleared in-memory sessions (if not persisted); session deleted from another tab or by the sessions UI; hand-crafted session_id values.
Related errors
- Session not found
- Session {session_id} not found
- Assistant session could not be resolved
- Not authenticated
- Integration not found
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/feb2512f78708d27.
Report an issue: GitHub.