{"record":{"id":"f426b783067299bc","repo":"odysseus-dev/odysseus","slug":"session-session-id-not-found","errorCode":null,"errorMessage":"Session {session_id} not found","messagePattern":"Session (.+?) not found","errorType":"exception","errorClass":"KeyError","httpStatus":404,"severity":"error","filePath":"core/session_manager.py","lineNumber":490,"sourceCode":"            session.message_count = (\n                db.query(DbChatMessage)\n                .filter(DbChatMessage.session_id == session_id)\n                .count()\n            )\n            return True\n        except Exception as e:\n            logger.error(f\"Error syncing session metadata {session_id}: {e}\")\n            return False\n        finally:\n            db.close()\n\n    def _load_session_from_db(self, session_id: str):\n        \"\"\"Hydrate a single session (with messages) from the database.\"\"\"\n        db = SessionLocal()\n        try:\n            db_session = db.query(DbSession).filter(DbSession.id == session_id).first()\n            if db_session is None:\n                raise KeyError(f\"Session {session_id} not found\")\n\n            session = self._db_to_session(db_session, db)\n            if session:\n                self.sessions[session_id] = session\n            else:\n                # No messages — fall back to metadata-only entry so callers\n                # don't crash on KeyError for empty sessions.\n                meta = self._db_to_session_meta(db_session)\n                if meta is None:\n                    raise KeyError(f\"Session {session_id} could not be loaded\")\n                self.sessions[session_id] = meta\n\n        except KeyError:\n            raise\n        except Exception as e:\n            logger.error(f\"Error loading session {session_id}: {e}\")\n            raise\n        finally:","sourceCodeStart":472,"sourceCodeEnd":508,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/core/session_manager.py#L472-L508","documentation":"KeyError from _load_session_from_db when no DbSession row with the given id exists. It is the hydrate-on-demand path: the loader queries by id, and a miss means the session was never created or was deleted, so it cannot be cached or returned.","triggerScenarios":"Calling get_session/load for an id not present in the sessions table — e.g. after the session was deleted on another device/request, a client retrying with a stale id, or a typo/garbled id.","commonSituations":"Client holds a session id across a delete; race between delete and a concurrent read; restoring from backup where message rows exist but the session row is gone.","solutions":["Handle KeyError by listing sessions (get_sessions_for_user) and reselecting a valid id","Create a new session instead of reusing the stale id","If the session should exist, check the DbSession table for the row and any delete/retention job that removed it"],"exampleFix":"# before\nsession = sm.get_session(session_id)  # KeyError if deleted\n# after\ntry:\n    session = sm.get_session(session_id)\nexcept KeyError:\n    session = sm.create_session(...)\n    session_id = session.id","handlingStrategy":"try-catch","validationCode":"existing = db.query(DbSession.id).filter(DbSession.id == session_id).first()\nif existing is None:\n    raise ClientVisibleError('Session was deleted')","typeGuard":null,"tryCatchPattern":"try:\n    session = sm.get_session(session_id)\nexcept KeyError:\n    session = sm.create_session(owner=owner)\n    session_id = session.id","preventionTips":["Treat KeyError as 'session gone' and resync from the session list","Create a fresh session rather than reusing ids held across restarts","Audit retention/delete jobs when sessions vanish unexpectedly"],"tags":["session","not-found","database"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}