D4Vinci/Scrapling · error · ValueError
Session '{session_id}' already exists. Use a different ID or
Error message
Session '{session_id}' already exists. Use a different ID or close the existing session first. What it means
open_session generates a random 12-hex-char ID when none is supplied, but if a caller-provided session_id already exists in the registry it raises this ValueError to prevent silently hijacking an existing browser session. Duplicate IDs would otherwise alias two live sessions and corrupt resource tracking.
Source
Thrown at scrapling/core/ai.py:235
:param useragent: Pass a useragent string to be used. Otherwise the fetcher will generate a real Useragent of the same browser and use it.
:param cdp_url: Instead of launching a new browser instance, connect to this CDP URL to control real browsers through CDP.
:param executable_path: Absolute path to a custom Chromium-compatible browser executable. Overrides the server-wide default for this session.
:param timeout: The timeout in milliseconds that is used in all operations and waits through the page. The default is 30,000.
:param disable_resources: Drop requests for unnecessary resources for a speed boost.
:param wait_selector: Wait for a specific CSS selector to be in a specific state.
:param cookies: Set cookies for the session. It should be in a dictionary format that Playwright accepts.
:param network_idle: Wait for the page until there are no network connections for at least 500 ms.
:param wait_selector_state: The state to wait for the selector given with `wait_selector`. The default state is `attached`.
:param max_pages: Maximum number of concurrent pages/tabs in the browser. Defaults to 5. Higher values allow more parallel fetches.
:param hide_canvas: (Stealthy only) Add random noise to canvas operations to prevent fingerprinting.
:param block_webrtc: (Stealthy only) Forces WebRTC to respect proxy settings to prevent local IP address leak.
:param allow_webgl: (Stealthy only) Enabled by default. Disabling WebGL is not recommended as many WAFs now check if WebGL is enabled.
:param solve_cloudflare: (Stealthy only) Solves all types of the Cloudflare's Turnstile/Interstitial challenges.
:param additional_args: (Stealthy only) Additional arguments to be passed to Playwright's context as additional settings.
"""
session_id = session_id or uuid4().hex[:12]
if session_id in self._sessions:
raise ValueError(
f"Session '{session_id}' already exists. Use a different ID or close the existing session first."
)
common_kwargs: Dict[str, Any] = dict(
wait=wait,
proxy=proxy,
locale=locale,
timeout=timeout,
cookies=cookies,
cdp_url=cdp_url,
headless=headless,
block_ads=True,
max_pages=max_pages,
useragent=useragent,
timezone_id=timezone_id,
real_chrome=real_chrome,
network_idle=network_idle,
wait_selector=wait_selector,View on GitHub (pinned to 5d213a2d47)
Solutions
- Check list_sessions and reuse the existing session instead of reopening
- Or close_session(id) first, then open again with the same ID
- Omit session_id to let Scrapling generate a unique one, and store the returned ID
Example fix
# before
await open_session(session_type='dynamic', session_id='main')
await open_session(session_type='dynamic', session_id='main') # ValueError: already exists
# after
existing = {s.session_id for s in await list_sessions()}
if 'main' not in existing:
await open_session(session_type='dynamic', session_id='main') Defensive patterns
Strategy: validation
Validate before calling
if any(s.session_id == 'main' for s in await list_sessions()):
await close_session('main')
await open_session(session_type='dynamic', session_id='main') Prevention
- Prefer generated IDs (omit session_id) and track returned values
- In retry loops, check list_sessions before re-opening with a fixed ID
When it happens
Trigger: Calling open_session twice with the same explicit session_id without closing the first, e.g. deterministic IDs like 'main' reused across retry loops or repeated agent turns.
Common situations: Agents using fixed session names ('default', 'browser') across steps, or retry logic that re-invokes open_session after a partial failure while the first session actually opened fine.
Related errors
- Credentials dictionary must contain both 'username' and 'pas
- Session '{session_id}' not found. Use list_sessions to see a
- Session '{session_id}' is no longer alive. Open a new sessio
- Session '{session_id}' is a '{entry.session_type}' session,
- 'quality' is only valid when 'image_type' is 'jpeg'.
AI-assisted analysis of D4Vinci/Scrapling@5d213a2d47 (2026-08-14).
Data as JSON: /api/errors/fc9f270e01ddb87d.
Report an issue: GitHub.