{"record":{"id":"49c20e8263cd2e5e","repo":"D4Vinci/Scrapling","slug":"session-session-id-not-found-use-list-session","errorCode":null,"errorMessage":"Session '{session_id}' not found. Use list_sessions to see active sessions.","messagePattern":"Session '(.+?)' not found\\. Use list_sessions to see active sessions\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"scrapling/core/ai.py","lineNumber":165,"sourceCode":"        :param executable_path: Optional global Chromium-compatible browser executable path for browser tools.\n            If omitted, the SCRAPLING_EXECUTABLE_PATH environment variable is used when set.\n        :param auth_token: Optional shared token that clients must send as `Authorization: Bearer <token>`.\n            If omitted, the SCRAPLING_MCP_AUTH_TOKEN environment variable is used when set. It only applies\n            to the streamable-http transport.\n        \"\"\"\n        self._sessions: Dict[str, _SessionEntry] = {}\n        self._executable_path = executable_path or environ.get(MCP_EXECUTABLE_PATH_ENV) or None\n        self._auth_token = auth_token or environ.get(MCP_AUTH_TOKEN_ENV) or None\n\n    def _resolve_executable_path(self, executable_path: Optional[str]) -> Optional[str]:\n        \"\"\"Return a per-call executable path or the server-wide default.\"\"\"\n        return executable_path or self._executable_path\n\n    def _get_session(self, session_id: str, expected_type: Optional[SessionType]) -> _SessionEntry:\n        \"\"\"Look up a session by ID, optionally validating its type. Pass `None` to skip the type check.\"\"\"\n        entry = self._sessions.get(session_id)\n        if entry is None:\n            raise ValueError(f\"Session '{session_id}' not found. Use list_sessions to see active sessions.\")\n        if not entry.session._is_alive:\n            raise ValueError(f\"Session '{session_id}' is no longer alive. Open a new session.\")\n        if expected_type is not None and entry.session_type != expected_type:\n            raise ValueError(\n                f\"Session '{session_id}' is a '{entry.session_type}' session, but this tool requires a \"\n                f\"'{expected_type}' session. Use the matching fetch tool for your session type.\"\n            )\n        return entry\n\n    async def open_session(\n        self,\n        session_type: SessionType,\n        session_id: Optional[str] = None,\n        headless: bool = True,\n        google_search: bool = True,\n        real_chrome: bool = False,\n        wait: int | float = 0,\n        proxy: Optional[str | Dict[str, str]] = None,","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/D4Vinci/Scrapling/blob/5d213a2d4764002bfc4fed33c32fe09fa8b0bf7f/scrapling/core/ai.py#L147-L183","documentation":"The MCP browser-session manager keeps sessions in a dict keyed by session_id. _get_session raises this ValueError when the ID is absent — i.e. the session was never opened in this server process, was closed, or belongs to a different run. Every tool that operates on an existing session (fetch in session, screenshot, close) goes through this lookup.","triggerScenarios":"Calling screenshot_session/fetch_with_session/close_session with a session_id that was never opened, was already closed (or auto-closed after a crash), or after the MCP server restarted (in-memory registry wiped). Also using an ID from a different server instance.","commonSituations":"LLM agents reusing a stale session ID across conversation turns after the server restarted, IDs truncated/typo'd when copied, or two clients sharing one MCP server and mixing up IDs.","solutions":["Call list_sessions first and use one of the returned session_id values","If the list is empty or the ID is missing, open_session again and use the new ID","Open sessions with an explicit session_id you control so IDs are predictable and loggable","After any MCP server restart, treat all previous session IDs as invalid"],"exampleFix":"# before\nawait screenshot_session(session_id='abc123', url='https://example.com')\n# ValueError: Session 'abc123' not found...\n\n# after\ninfos = await list_sessions()\nsid = infos[0].session_id if infos else (await open_session('session_type'='dynamic')).session_id\nawait screenshot_session(session_id=sid, url='https://example.com')","handlingStrategy":"validation","validationCode":"sessions = {s.session_id: s for s in await list_sessions()}\nif session_id not in sessions:\n    opened = await open_session(session_type='dynamic')\n    session_id = opened.session_id","typeGuard":null,"tryCatchPattern":"try:\n    result = await fetch_with_session(session_id=sid, url=url)\nexcept ValueError as e:\n    if 'not found' in str(e):\n        sid = (await open_session(session_type='dynamic')).session_id\n        result = await fetch_with_session(session_id=sid, url=url)\n    else:\n        raise","preventionTips":["Always call list_sessions before reusing an ID across agent turns","Store the session_id returned by open_session; never hand-type IDs","Assume all sessions are invalid after an MCP server restart"],"tags":["ai","mcp","session","state"],"backgroundTag":null,"analyzedSha":"5d213a2d4764002bfc4fed33c32fe09fa8b0bf7f","analyzedAt":"2026-08-14T22:23:09.440Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}