{"record":{"id":"a1f32e69cee19107","repo":"D4Vinci/Scrapling","slug":"session-session-id-is-a-entry-session-type","errorCode":null,"errorMessage":"Session '{session_id}' is a '{entry.session_type}' session, but this tool requires a '{expected_type}' session. Use the matching fetch tool for your session type.","messagePattern":"Session '(.+?)' is a '(.+?)' session, but this tool requires a '(.+?)' session\\. Use the matching fetch tool for your session type\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"scrapling/core/ai.py","lineNumber":169,"sourceCode":"            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,\n        timezone_id: str | None = None,\n        locale: str | None = None,\n        extra_headers: Optional[Dict[str, str]] = None,\n        useragent: Optional[str] = None,","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/D4Vinci/Scrapling/blob/5d213a2d4764002bfc4fed33c32fe09fa8b0bf7f/scrapling/core/ai.py#L151-L187","documentation":"Sessions are typed (e.g. 'dynamic' vs 'stealthy') and tools that act on a session validate the type via _get_session(expected_type=...). Using a tool meant for one session type against the other raises this ValueError instead of silently running the wrong fetcher. Pass expected_type=None (as the screenshot tool does) to operate on any session type.","triggerScenarios":"Opening a session with session_type='dynamic' and then calling the stealthy-specific fetch tool (or vice versa), e.g. fetch_with_stealthy_session on a dynamic session. Each fetch tool is bound to its engine, so the mismatch is rejected up front.","commonSituations":"LLM agents mixing up tool names after opening a cheaper dynamic session, or a workflow that switched from StealthyFetcher to DynamicFetcher for speed but kept calling the old tool.","solutions":["Use the fetch tool that matches the session_type you opened (dynamic tool for dynamic sessions, stealthy tool for stealthy sessions)","Or close and reopen the session with the type your tool requires","Call list_sessions to confirm each session's type before dispatching"],"exampleFix":"# before\nsid = (await open_session(session_type='dynamic', ...)).session_id\nawait fetch_with_stealthy_session(session_id=sid, url=url)\n\n# after\nsid = (await open_session(session_type='stealthy', ...)).session_id\nawait fetch_with_stealthy_session(session_id=sid, url=url)","handlingStrategy":"validation","validationCode":"sessions = {s.session_id: s.session_type for s in await list_sessions()}\nif sessions.get(sid) != 'stealthy':\n    raise RuntimeError(f'{sid} is {sessions.get(sid)}; open a stealthy session for this tool')","typeGuard":"def tool_matches_session(tool_name: str, session_type: str) -> bool:\n    return session_type in tool_name  # 'dynamic' in fetch_with_dynamic_session, etc.","tryCatchPattern":null,"preventionTips":["Derive the session_type from the tool you plan to call (and vice versa) instead of choosing independently","Record the intended tool type alongside each stored session_id"],"tags":["ai","mcp","session","type-mismatch"],"backgroundTag":null,"analyzedSha":"5d213a2d4764002bfc4fed33c32fe09fa8b0bf7f","analyzedAt":"2026-08-14T22:23:09.440Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}