D4Vinci/Scrapling · error · ValueError

Session '{session_id}' is a '{entry.session_type}' session,

Error message

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.

What it means

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.

Source

Thrown at scrapling/core/ai.py:169

            to the streamable-http transport.
        """
        self._sessions: Dict[str, _SessionEntry] = {}
        self._executable_path = executable_path or environ.get(MCP_EXECUTABLE_PATH_ENV) or None
        self._auth_token = auth_token or environ.get(MCP_AUTH_TOKEN_ENV) or None

    def _resolve_executable_path(self, executable_path: Optional[str]) -> Optional[str]:
        """Return a per-call executable path or the server-wide default."""
        return executable_path or self._executable_path

    def _get_session(self, session_id: str, expected_type: Optional[SessionType]) -> _SessionEntry:
        """Look up a session by ID, optionally validating its type. Pass `None` to skip the type check."""
        entry = self._sessions.get(session_id)
        if entry is None:
            raise ValueError(f"Session '{session_id}' not found. Use list_sessions to see active sessions.")
        if not entry.session._is_alive:
            raise ValueError(f"Session '{session_id}' is no longer alive. Open a new session.")
        if expected_type is not None and entry.session_type != expected_type:
            raise ValueError(
                f"Session '{session_id}' is a '{entry.session_type}' session, but this tool requires a "
                f"'{expected_type}' session. Use the matching fetch tool for your session type."
            )
        return entry

    async def open_session(
        self,
        session_type: SessionType,
        session_id: Optional[str] = None,
        headless: bool = True,
        google_search: bool = True,
        real_chrome: bool = False,
        wait: int | float = 0,
        proxy: Optional[str | Dict[str, str]] = None,
        timezone_id: str | None = None,
        locale: str | None = None,
        extra_headers: Optional[Dict[str, str]] = None,
        useragent: Optional[str] = None,

View on GitHub (pinned to 5d213a2d47)

Solutions

  1. Use the fetch tool that matches the session_type you opened (dynamic tool for dynamic sessions, stealthy tool for stealthy sessions)
  2. Or close and reopen the session with the type your tool requires
  3. Call list_sessions to confirm each session's type before dispatching

Example fix

# before
sid = (await open_session(session_type='dynamic', ...)).session_id
await fetch_with_stealthy_session(session_id=sid, url=url)

# after
sid = (await open_session(session_type='stealthy', ...)).session_id
await fetch_with_stealthy_session(session_id=sid, url=url)
Defensive patterns

Strategy: validation

Validate before calling

sessions = {s.session_id: s.session_type for s in await list_sessions()}
if sessions.get(sid) != 'stealthy':
    raise RuntimeError(f'{sid} is {sessions.get(sid)}; open a stealthy session for this tool')

Type guard

def tool_matches_session(tool_name: str, session_type: str) -> bool:
    return session_type in tool_name  # 'dynamic' in fetch_with_dynamic_session, etc.

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of D4Vinci/Scrapling@5d213a2d47 (2026-08-14). Data as JSON: /api/errors/a1f32e69cee19107. Report an issue: GitHub.