{"record":{"id":"edb91d6457e09f2d","repo":"D4Vinci/Scrapling","slug":"argument-selector-config-must-be-a-dictionary","errorCode":null,"errorMessage":"Argument `selector_config` must be a dictionary.","messagePattern":"Argument `selector_config` must be a dictionary\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"scrapling/fetchers/chrome.py","lineNumber":46,"sourceCode":"        :param wait_selector: Wait for a specific CSS selector to be in a specific state.\n        :param init_script: An absolute path to a JavaScript file to be executed on page creation with this request.\n        :param locale: Set the locale for the browser if wanted. Defaults to the system default locale.\n        :param wait_selector_state: The state to wait for the selector given with `wait_selector`. The default state is `attached`.\n        :param real_chrome: If you have a Chrome browser installed on your device, enable this, and the Fetcher will launch an instance of your browser and use it.\n        :param cdp_url: Instead of launching a new browser instance, connect to this CDP URL to control real browsers through CDP.\n        :param google_search: Enabled by default, Scrapling will set a Google referer header.\n        :param extra_headers: A dictionary of extra headers to add to the request.\n        :param proxy: The proxy to be used with requests, it can be a string or a dictionary with the keys 'server', 'username', and 'password' only.\n        :param extra_flags: A list of additional browser flags to pass to the browser on launch.\n        :param selector_config: The arguments that will be passed in the end while creating the final Selector's class.\n        :param additional_args: Additional arguments to be passed to Playwright's context as additional settings.\n        :return: A `Response` object.\n        \"\"\"\n        selector_config = kwargs.get(\"selector_config\", {}) or kwargs.get(\n            \"custom_config\", {}\n        )  # Checking `custom_config` for backward compatibility\n        if not isinstance(selector_config, dict):\n            raise TypeError(\"Argument `selector_config` must be a dictionary.\")\n\n        kwargs[\"selector_config\"] = {**cls._generate_parser_arguments(), **selector_config}\n\n        with DynamicSession(**kwargs) as session:\n            return session.fetch(url)\n\n    @classmethod\n    async def async_fetch(cls, url: str, **kwargs: Unpack[PlaywrightSession]) -> Response:\n        \"\"\"Opens up a browser and do your request based on your chosen options below.\n\n        :param url: Target url.\n        :param headless: Run the browser in headless/hidden (default), or headful/visible mode.\n        :param disable_resources: Drop requests for unnecessary resources for a speed boost.\n        :param blocked_domains: A set of domain names to block requests to. Subdomains are also matched (e.g., ``\"example.com\"`` blocks ``\"sub.example.com\"`` too).\n        :param block_ads: Block requests to ~3,500 known ad/tracking domains. Can be combined with ``blocked_domains``.\n        :param dns_over_https: Route DNS queries through Cloudflare's DNS-over-HTTPS to prevent DNS leaks when using proxies.\n        :param useragent: Pass a useragent string to be used. Otherwise the fetcher will generate a real Useragent of the same browser and use it.\n        :param cookies: Set cookies for the next request.","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/D4Vinci/Scrapling/blob/5d213a2d4764002bfc4fed33c32fe09fa8b0bf7f/scrapling/fetchers/chrome.py#L28-L64","documentation":"Raised by `DynamicFetcher.fetch` (scrapling/fetchers/chrome.py) when the `selector_config` keyword argument is not a dict. selector_config carries arguments forwarded to the final Selector class; it also accepts the legacy `custom_config` key for backward compatibility, but whichever value wins must be a dictionary.","triggerScenarios":"DynamicFetcher.fetch(url, selector_config=SelectorConfig(...)) with a dataclass/object instead of a dict, selector_config='text=True' as a string, or custom_config=[('adaptive', True)] as a list of tuples.","commonSituations":"Porting code from another library whose config is an object; passing a JSON string straight from a config file; using the old `custom_config` name with a non-dict value.","solutions":["Pass a plain dict: DynamicFetcher.fetch(url, selector_config={'adaptive': True, 'keep_comments': False}).","If you have an object, convert with vars(obj) or dataclasses.asdict(obj) first.","Rename custom_config to selector_config (old name still works but only with dict values)."],"exampleFix":"# before\nDynamicFetcher.fetch(url, selector_config='adaptive=True')\n\n# after\nDynamicFetcher.fetch(url, selector_config={'adaptive': True})","handlingStrategy":"validation","validationCode":"selector_config = selector_config if isinstance(selector_config, dict) else {}\nDynamicFetcher.fetch(url, selector_config=selector_config)","typeGuard":"def is_selector_config(value: object) -> bool:\n    return isinstance(value, dict)","tryCatchPattern":"try:\n    DynamicFetcher.fetch(url, selector_config=cfg)\nexcept TypeError as e:\n    if \"selector_config\" in str(e):\n        return DynamicFetcher.fetch(url, selector_config=dict(cfg))  # or {}\n    raise","preventionTips":["Always pass selector_config as a plain dict of Selector kwargs.","Default to {} (or omit) rather than None.","Convert config objects with dataclasses.asdict before the call."],"tags":["fetcher","selector-config","type-error","validation","playwright"],"backgroundTag":null,"analyzedSha":"5d213a2d4764002bfc4fed33c32fe09fa8b0bf7f","analyzedAt":"2026-08-14T22:23:09.440Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}