{"record":{"id":"b4d9e8760f91a432","repo":"D4Vinci/Scrapling","slug":"cannot-use-proxy-rotator-together-with-proxy-o","errorCode":null,"errorMessage":"Cannot use 'proxy_rotator' together with 'proxy' or 'proxies'. Use either a static proxy or proxy rotation, not both.","messagePattern":"Cannot use 'proxy_rotator' together with 'proxy' or 'proxies'\\. Use either a static proxy or proxy rotation, not both\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"scrapling/engines/static.py","lineNumber":92,"sourceCode":"        self._stealth = kwargs.get(\"stealthy_headers\", True)\n        self._default_proxies = kwargs.get(\"proxies\") or {}\n        self._default_proxy = kwargs.get(\"proxy\") or None\n        self._default_proxy_auth = kwargs.get(\"proxy_auth\") or None\n        self._default_timeout = kwargs.get(\"timeout\", 30)\n        self._default_headers = kwargs.get(\"headers\") or {}\n        self._default_retries = kwargs.get(\"retries\", 3)\n        self._default_retry_delay = kwargs.get(\"retry_delay\", 1)\n        self._default_follow_redirects = kwargs.get(\"follow_redirects\", \"safe\")\n        self._default_max_redirects = kwargs.get(\"max_redirects\", 30)\n        self._default_verify = kwargs.get(\"verify\", True)\n        self._default_cert = kwargs.get(\"cert\") or None\n        self._default_http3 = kwargs.get(\"http3\", False)\n        self.selector_config = kwargs.get(\"selector_config\") or {}\n        self._is_alive = False\n        self._proxy_rotator: Optional[ProxyRotator] = kwargs.get(\"proxy_rotator\")\n\n        if self._proxy_rotator and (self._default_proxy or self._default_proxies):\n            raise ValueError(\n                \"Cannot use 'proxy_rotator' together with 'proxy' or 'proxies'. \"\n                \"Use either a static proxy or proxy rotation, not both.\"\n            )\n\n    @staticmethod\n    def _get_param(kwargs: Dict, key: str, default: Any) -> Any:\n        \"\"\"Get parameter from kwargs if present, otherwise return default.\"\"\"\n        return kwargs[key] if key in kwargs else default\n\n    def _merge_request_args(self, **method_kwargs) -> Dict[str, Any]:\n        \"\"\"Merge request-specific arguments with default session arguments.\"\"\"\n        url = method_kwargs.pop(\"url\")\n\n        # Get parameters from kwargs or use defaults\n        impersonate = self._get_param(method_kwargs, \"impersonate\", self._default_impersonate)\n        impersonate = _select_random_browser(impersonate)\n        http3_enabled = self._get_param(method_kwargs, \"http3\", self._default_http3)\n        stealth = self._get_param(method_kwargs, \"stealth\", self._stealth)","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/D4Vinci/Scrapling/blob/5d213a2d4764002bfc4fed33c32fe09fa8b0bf7f/scrapling/engines/static.py#L74-L110","documentation":"Raised in _ConfigurationLogic.__init__ (the base of every static fetcher/session class) when the constructor receives both a proxy_rotator and a static proxy/proxies argument. Scrapling treats proxy rotation and static proxying as mutually exclusive strategies, so it fails fast at construction time instead of silently letting one override the other. This is a configuration contract error, not a network error.","triggerScenarios":"Calling FetcherSession(proxy='http://...', proxy_rotator=rotator), AsyncFetcherSession(proxies={...}, proxy_rotator=rotator), or any static fetcher class (Fetcher/AsyncFetcher) with both kwargs set. Also triggered when a FetcherSession forwards its saved config into an inner _SyncSessionLogic/_ASyncSessionLogic while both fields were somehow populated.","commonSituations":"Copy-pasting a proxy from an existing scraper while adding the new ProxyRotator feature; migrating from static proxies to rotation and forgetting to delete the old 'proxy' kwarg; passing a dict of proxies that was valid pre-rotator versions.","solutions":["Remove the 'proxy' (or 'proxies') kwarg and keep only proxy_rotator if you want rotating proxies.","Or remove proxy_rotator and keep the static 'proxy'/'proxies' kwarg if you want a single fixed proxy.","If you need a fallback static proxy, encode it as the last entry inside the ProxyRotator's proxy list instead of a separate kwarg."],"exampleFix":"# before\nsession = FetcherSession(proxy='http://10.0.0.1:8080', proxy_rotator=ProxyRotator([...]))\n\n# after\nsession = FetcherSession(proxy_rotator=ProxyRotator(['http://10.0.0.1:8080', 'http://10.0.0.2:8080']))","handlingStrategy":"validation","validationCode":"from scrapling.engines.proxy import ProxyRotator\n\ndef make_static_fetcher(proxy=None, proxies=None, proxy_rotator=None):\n    if proxy_rotator is not None and (proxy or proxies):\n        raise ValueError('Choose one: static proxy OR proxy_rotator, not both')\n    return FetcherSession(proxy=proxy, proxies=proxies, proxy_rotator=proxy_rotator)","typeGuard":"def has_exclusive_proxy_config(proxy, proxies, rotator) -> bool:\n    return not (rotator is not None and (proxy is not None or proxies is not None))","tryCatchPattern":"try:\n    session = FetcherSession(proxy=proxy, proxy_rotator=rotator)\nexcept ValueError as e:\n    if 'proxy_rotator' in str(e):\n        # config conflict: drop the static proxy and rebuild\n        session = FetcherSession(proxy_rotator=rotator)\n    else:\n        raise","preventionTips":["Keep proxy configuration in one place (a dataclass or config dict) with a single 'mode' field.","Assert the exclusivity invariant in your own factory before constructing fetchers.","When migrating to ProxyRotator, grep for 'proxy=' and 'proxies=' to remove leftovers."],"tags":["configuration","proxy","validation","static-fetcher"],"backgroundTag":null,"analyzedSha":"5d213a2d4764002bfc4fed33c32fe09fa8b0bf7f","analyzedAt":"2026-08-14T22:23:09.440Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}