{"record":{"id":"743df858f2ac2a43","repo":"D4Vinci/Scrapling","slug":"this-fetchersession-instance-already-has-an-active","errorCode":null,"errorMessage":"This FetcherSession instance already has an active synchronous session.","messagePattern":"This FetcherSession instance already has an active synchronous session\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"scrapling/engines/static.py","lineNumber":204,"sourceCode":"\n        elif \"user-agent\" not in headers_keys and not impersonate_enabled:  # pragma: no cover\n            final_headers[\"User-Agent\"] = __default_useragent__\n            log.debug(f\"Can't find useragent in headers so '{final_headers['User-Agent']}' was used.\")\n\n        return final_headers\n\n\nclass _SyncSessionLogic(_ConfigurationLogic):\n    __slots__ = (\"_curl_session\",)\n\n    def __init__(self, **kwargs: Unpack[RequestsSession]):\n        super().__init__(**kwargs)\n        self._curl_session: Optional[CurlSession] = None\n\n    def __enter__(self):\n        \"\"\"Creates and returns a new synchronous Fetcher Session\"\"\"\n        if self._is_alive:\n            raise RuntimeError(\"This FetcherSession instance already has an active synchronous session.\")\n\n        self._curl_session = CurlSession()\n        self._is_alive = True\n        return self\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        \"\"\"Closes the active synchronous session managed by this instance, if any.\"\"\"\n        # For type checking (not accessed error)\n        _ = (\n            exc_type,\n            exc_val,\n            exc_tb,\n        )\n        if self._curl_session:\n            self._curl_session.close()\n            self._curl_session = None\n\n        self._is_alive = False","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/D4Vinci/Scrapling/blob/5d213a2d4764002bfc4fed33c32fe09fa8b0bf7f/scrapling/engines/static.py#L186-L222","documentation":"Raised by _SyncSessionLogic.__enter__ when you enter the same synchronous session object twice. A _SyncSessionLogic/FetcherSession instance holds exactly one underlying curl_cffi CurlSession and tracks it with the _is_alive flag, so a second __enter__ before __exit__ is rejected. It protects the single curl handle from being clobbered by a nested 'with' on the same instance.","triggerScenarios":"Calling session.__enter__() manually twice; using 'with session:' while already inside another 'with session:' block on the identical instance; re-entering a FetcherSession's inner client after the outer FetcherSession.__enter__ already created it.","commonSituations":"Sharing one module-level FetcherSession across functions where one function nests inside another that already opened it; writing a recursive fetch helper that re-opens the session passed as a parameter; reusing a session in a loop that wraps the body in 'with' twice.","solutions":["Use 'with session:' exactly once per instance and do all requests inside that single block.","If you need nested/concurrent usage, create a separate FetcherSession instance for each context.","For fire-and-forget requests without context management, use FetcherClient (or the top-level fetch functions), which creates one-off sessions internally."],"exampleFix":"# before\nwith session:\n    resp = session.get(url)\n    with session:  # RuntimeError\n        resp2 = session.get(url2)\n\n# after\nwith session:\n    resp = session.get(url)\n    resp2 = session.get(url2)","handlingStrategy":"validation","validationCode":"session = FetcherSession(...)\nif session._is_alive:  # avoid depending on privates in production; prefer structural fix\n    raise RuntimeError('session already open')\nwith session as s:\n    s.get(url)","typeGuard":"def is_session_open(session) -> bool:\n    return getattr(session, '_is_alive', False)","tryCatchPattern":"try:\n    with session:\n        session.get(url)\nexcept RuntimeError as e:\n    if 'already has an active' in str(e):\n        # session was left open: reuse it instead of re-entering\n        session.get(url)\n    else:\n        raise","preventionTips":["Enter each session exactly once, at the outermost scope that uses it.","Never share one FetcherSession instance across functions that each open 'with'.","Use FetcherClient when you don't want lifecycle management at all."],"tags":["session-lifecycle","static-fetcher","context-manager","sync"],"backgroundTag":null,"analyzedSha":"5d213a2d4764002bfc4fed33c32fe09fa8b0bf7f","analyzedAt":"2026-08-14T22:23:09.440Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}