{"record":{"id":"bf059a5aaab78cb5","repo":"unclecode/crawl4ai","slug":"crawlerrunconfig-must-be-provided-bf059a","errorCode":null,"errorMessage":"CrawlerRunConfig must be provided","messagePattern":"CrawlerRunConfig must be provided","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"crawl4ai/deep_crawling/bff_strategy.py","lineNumber":406,"sourceCode":"        Yields CrawlResults as they become available.\n        \"\"\"\n        async for result in self._arun_best_first(start_url, crawler, config):\n            yield result\n\n    async def arun(\n        self,\n        start_url: str,\n        crawler: AsyncWebCrawler,\n        config: Optional[CrawlerRunConfig] = None,\n    ) -> \"RunManyReturn\":\n        \"\"\"\n        Main entry point for best-first crawling.\n        \n        Returns either a list (batch mode) or an async generator (stream mode)\n        of CrawlResults.\n        \"\"\"\n        if config is None:\n            raise ValueError(\"CrawlerRunConfig must be provided\")\n        if config.stream:\n            return self._arun_stream(start_url, crawler, config)\n        else:\n            return await self._arun_batch(start_url, crawler, config)\n\n    async def shutdown(self) -> None:\n        \"\"\"\n        Signal cancellation and clean up resources.\n        \"\"\"\n        self._cancel_event.set()\n        self.stats.end_time = datetime.now()\n\n    def export_state(self) -> Optional[Dict[str, Any]]:\n        \"\"\"\n        Export current crawl state for external persistence.\n\n        Note: This returns the last captured state. For real-time state,\n        use the on_state_change callback.","sourceCodeStart":388,"sourceCodeEnd":424,"githubUrl":"https://github.com/unclecode/crawl4ai/blob/7e801521428ee12509994d39151006f64055ebe3/crawl4ai/deep_crawling/bff_strategy.py#L388-L424","documentation":"Raised by BestFirstCrawlingStrategy.arun when the config argument is None. Although the signature declares config: Optional[CrawlerRunConfig] = None, the method body immediately rejects None because best-first crawling needs run settings (depth, stream mode, link filtering) to operate. It is a usage error, not a runtime failure.","triggerScenarios":"Calling strategy.arun(start_url, crawler) or await strategy.arun(start_url, crawler, config=None) without a third argument. This happens when users port code from older crawl4ai versions where the config parameter was optional or positioned differently.","commonSituations":"Upgrading from an older crawl4ai release where arun(start_url, crawler) worked; constructing the strategy manually instead of via CrawlerRunConfig.deep_crawl_strategy and forgetting to forward the run config; copying examples that omit config.","solutions":["Pass a CrawlerRunConfig instance as the third argument: await strategy.arun(start_url, crawler, config=CrawlerRunConfig(...))","If using deep crawling normally, set deep_crawl_strategy=BestFirstCrawlingStrategy(...) on CrawlerRunConfig and call crawler.arun(url, config=config) so the library forwards the config itself","Set stream=True/False on the config explicitly if you need batch vs generator behavior"],"exampleFix":"// before\nstrategy = BestFirstCrawlingStrategy(...)\nresults = await strategy.arun(start_url, crawler)  # ValueError\n\n// after\nfrom crawl4ai import CrawlerRunConfig\nconfig = CrawlerRunConfig(depth=2, stream=False)\nresults = await strategy.arun(start_url, crawler, config)","handlingStrategy":"validation","validationCode":"from crawl4ai import CrawlerRunConfig\nassert config is not None, \"BestFirstCrawlingStrategy.arun requires a CrawlerRunConfig\"\nif not isinstance(config, CrawlerRunConfig):\n    raise TypeError(f\"expected CrawlerRunConfig, got {type(config).__name__}\")\nresults = await strategy.arun(start_url, crawler, config)","typeGuard":"from crawl4ai.async_configs import CrawlerRunConfig\n\ndef is_run_config(cfg) -> bool:\n    return isinstance(cfg, CrawlerRunConfig)","tryCatchPattern":"try:\n    results = await strategy.arun(start_url, crawler, config)\nexcept ValueError as e:\n    if \"must be provided\" in str(e):\n        raise RuntimeError(\"deep-crawl config missing\") from e\n    raise","preventionTips":["Always construct a CrawlerRunConfig and pass it explicitly to arun","Prefer wiring BestFirstCrawlingStrategy through CrawlerRunConfig.deep_crawl_strategy so the library forwards config itself","Add a unit assertion that config is not None before calling arun in pipeline code"],"tags":["deep-crawling","config","api-usage"],"backgroundTag":null,"analyzedSha":"7e801521428ee12509994d39151006f64055ebe3","analyzedAt":"2026-08-14T20:46:20.673Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}