{"record":{"id":"a2134640af859b15","repo":"D4Vinci/Scrapling","slug":"invalid-proxy-type-type-proxy-expected-str-or","errorCode":null,"errorMessage":"Invalid proxy type: {type(proxy)}. Expected str or dict.","messagePattern":"Invalid proxy type: (.+?)\\. Expected str or dict\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"scrapling/engines/toolbelt/proxy_rotation.py","lineNumber":84,"sourceCode":"\n        if not callable(strategy):\n            raise TypeError(f\"strategy must be callable, got {type(strategy).__name__}\")\n\n        self._strategy = strategy\n        self._lock = Lock()\n\n        # Validate and store proxies\n        self._proxies: List[ProxyType] = []\n        self._proxy_to_index: Dict[str, int] = {}  # O(1) lookup by unique key (server + username)\n        for i, proxy in enumerate(proxies):\n            if isinstance(proxy, (str, dict)):\n                if isinstance(proxy, dict) and \"server\" not in proxy:\n                    raise ValueError(\"Proxy dict must have a 'server' key\")\n\n                self._proxy_to_index[_get_proxy_key(proxy)] = i\n                self._proxies.append(proxy)\n            else:\n                raise TypeError(f\"Invalid proxy type: {type(proxy)}. Expected str or dict.\")\n\n        self._current_index = 0\n\n    def get_proxy(self) -> ProxyType:\n        \"\"\"Get the next proxy according to the rotation strategy.\"\"\"\n        with self._lock:\n            proxy, self._current_index = self._strategy(self._proxies, self._current_index)\n            return proxy\n\n    @property\n    def proxies(self) -> List[ProxyType]:\n        \"\"\"Get a copy of all configured proxies.\"\"\"\n        return list(self._proxies)\n\n    def __len__(self) -> int:\n        \"\"\"Return the total number of configured proxies.\"\"\"\n        return len(self._proxies)\n","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/D4Vinci/Scrapling/blob/5d213a2d4764002bfc4fed33c32fe09fa8b0bf7f/scrapling/engines/toolbelt/proxy_rotation.py#L66-L102","documentation":"Raised during ProxyRotator construction when an element of the `proxies` list is neither a str nor a dict. The rotator iterates the list and type-checks every entry; any other type (None, tuple, nested list, object) is rejected with the offending type in the message.","triggerScenarios":"ProxyRotator(proxies=[None]), proxies=[('http', 'p', 8080)], proxies=[[\"http://p:8080\"]] (nested list), or a pool containing a raw config object.","commonSituations":"Placeholder entries from parsing blank lines in a proxy file; mixed data from JSON that deserializes tuples as lists; optional proxy slots filled with None.","solutions":["Make every entry a proxy URL string or a Playwright-style dict.","Filter the pool first: pool = [p for p in pool if isinstance(p, (str, dict)) and p].","Fix the parser that produced the pool so blank/malformed lines are dropped instead of yielded as None."],"exampleFix":"# before\npool = load_lines('proxies.txt')  # contains '' and None entries\nrotator = ProxyRotator(pool)\n\n# after\npool = [line.strip() for line in open('proxies.txt') if line.strip()]\nrotator = ProxyRotator(pool)","handlingStrategy":"type-guard","validationCode":"clean_pool = [p for p in pool if isinstance(p, (str, dict)) and p]\nif len(clean_pool) != len(pool):\n    log.warning(\"dropped %d malformed proxy entries\", len(pool) - len(clean_pool))\nrotator = ProxyRotator(proxies=clean_pool)","typeGuard":"def is_pool_entry(value: object) -> bool:\n    return isinstance(value, (str, dict))","tryCatchPattern":"try:\n    rotator = ProxyRotator(proxies=pool)\nexcept TypeError as e:\n    if \"Invalid proxy type\" in str(e):\n        pool = [p for p in pool if isinstance(p, (str, dict)) and p]\n        rotator = ProxyRotator(proxies=pool)\n    else:\n        raise","preventionTips":["Filter blank lines and None when parsing proxy files.","Never append placeholders (None/0/'') to proxy pools.","Type-check entries at ingest time, not at rotator construction."],"tags":["proxy","proxy-rotation","type-error","validation"],"backgroundTag":null,"analyzedSha":"5d213a2d4764002bfc4fed33c32fe09fa8b0bf7f","analyzedAt":"2026-08-14T22:23:09.440Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}