{"record":{"id":"a595591342cff113","repo":"unclecode/crawl4ai","slug":"unknown-strategy-strategy-name","errorCode":null,"errorMessage":"Unknown strategy: {strategy_name}","messagePattern":"Unknown strategy: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"critical","filePath":"crawl4ai/adaptive_crawler.py","lineNumber":1328,"sourceCode":"        self.state: Optional[CrawlState] = None\n        \n        # Track if we own the crawler (for cleanup)\n        self._owns_crawler = crawler is None\n    \n    def _create_strategy(self, strategy_name: str) -> CrawlStrategy:\n        \"\"\"Create strategy instance based on name\"\"\"\n        if strategy_name == \"statistical\":\n            return StatisticalStrategy()\n        elif strategy_name == \"embedding\":\n            strategy = EmbeddingStrategy(\n                embedding_model=self.config.embedding_model,\n                llm_config=self.config.embedding_llm_config,\n                query_llm_config=self.config.query_llm_config,\n            )\n            strategy.config = self.config  # Pass config to strategy\n            return strategy\n        else:\n            raise ValueError(f\"Unknown strategy: {strategy_name}\")\n    \n    async def digest(self, \n                               start_url: str, \n                               query: str,\n                               resume_from: Optional[str] = None) -> CrawlState:\n        \"\"\"Main entry point for adaptive crawling\"\"\"\n        # Initialize or resume state\n        if resume_from:\n            self.state = CrawlState.load(resume_from)\n            self.state.query = query  # Update query in case it changed\n        else:\n            self.state = CrawlState(\n                crawled_urls=set(),\n                knowledge_base=[],\n                pending_links=[],\n                query=query,\n                metrics={}\n            )","sourceCodeStart":1310,"sourceCodeEnd":1346,"githubUrl":"https://github.com/unclecode/crawl4ai/blob/7e801521428ee12509994d39151006f64055ebe3/crawl4ai/adaptive_crawler.py#L1310-L1346","documentation":"MemoryError raised by get_crawler before creating a new browser when container memory usage (get_container_memory_percent) is at or above MEM_LIMIT (config `crawler.memory_threshold_percent`, default 95%). It is a deliberate load-shed: the pool refuses to grow under memory pressure instead of letting the container get OOM-killed. Reusing a pooled crawler with the same signature bypasses the check; only new browser creation is gated.","triggerScenarios":"Issuing crawl requests with a new/distinct browser_config signature (forcing a new browser) while container memory is >= the threshold; typically when existing browsers have leaked memory or concurrency is too high. Existing hot/cold pool browsers with matching signatures are still handed out.","commonSituations":"Many unique browser configs in one deployment fragmenting the pool; long-running container with bloated browsers; memory threshold lowered in config; small container memory limit vs page weight.","solutions":["Reduce concurrent crawl load and let memory drain; retry once pressure drops below the threshold","Standardize browser_config across requests so pool reuse (no new browser) is possible","Raise the container memory limit or tune crawler.memory_threshold_percent if the threshold is set too close to steady-state usage","Restart the container / recycle idle browsers if leaked memory has permanently raised the baseline"],"exampleFix":"# server config: give headroom if steady-state sits near the threshold\n# config\n[crawler]\nmemory_threshold_percent = 90.0\n# plus docker: --memory=4g instead of 2g","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"for attempt in range(3):\n    try:\n        crawler = await get_crawler(cfg)\n        break\n    except MemoryError:\n        await asyncio.sleep(5 * (attempt + 1))  # let memory drain, then retry\nelse:\n    shed_load()  # queue or reject the request upstream","preventionTips":["Standardize browser_config so pooled crawlers are reused (no new-browser check)","Monitor container memory percent and alert below the configured threshold","Keep concurrency low enough that steady-state memory sits well under the threshold","Recycle long-lived browsers periodically to defragment leaked memory"],"tags":["memory","crawler-pool","load-shedding","resource-limits"],"backgroundTag":null,"analyzedSha":"7e801521428ee12509994d39151006f64055ebe3","analyzedAt":"2026-08-14T20:46:20.673Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}