{"record":{"id":"ce2e1143d9cb23cf","repo":"unclecode/crawl4ai","slug":"local-file-not-found-path","errorCode":null,"errorMessage":"Local file not found: {path}","messagePattern":"Local file not found: (.+?)","errorType":"exception","errorClass":"FileNotFoundError","httpStatus":null,"severity":"error","filePath":"crawl4ai/async_crawler_strategy.py","lineNumber":2582,"sourceCode":"            try:\n                await asyncio.wait_for(self._session.close(), timeout=5.0)\n            except asyncio.TimeoutError:\n                if self.logger:\n                    self.logger.warning(\n                        message=\"Session cleanup timed out\",\n                        tag=\"CLEANUP\"\n                    )\n            finally:\n                self._session = None\n\n    async def _stream_file(self, path: str) -> AsyncGenerator[memoryview, None]:\n        async with aiofiles.open(path, mode='rb') as f:\n            while chunk := await f.read(self.chunk_size):\n                yield memoryview(chunk)\n\n    async def _handle_file(self, path: str) -> AsyncCrawlResponse:\n        if not os.path.exists(path):\n            raise FileNotFoundError(f\"Local file not found: {path}\")\n            \n        chunks = []\n        async for chunk in self._stream_file(path):\n            chunks.append(chunk.tobytes().decode('utf-8', errors='replace'))\n            \n        return AsyncCrawlResponse(\n            html=''.join(chunks),\n            response_headers={},\n            status_code=200\n        )\n\n    async def _handle_raw(self, content: str, base_url: str = None) -> AsyncCrawlResponse:\n        return AsyncCrawlResponse(\n            html=content,\n            response_headers={},\n            status_code=200,\n            # For raw: URLs, use base_url if provided; don't fall back to the raw content\n            redirected_url=base_url","sourceCodeStart":2564,"sourceCodeEnd":2600,"githubUrl":"https://github.com/unclecode/crawl4ai/blob/7e801521428ee12509994d39151006f64055ebe3/crawl4ai/async_crawler_strategy.py#L2564-L2600","documentation":"Raised by the HTTP-mode crawler's _handle_file() when a file:// URL targets a path that does not exist. It uses urlparse(url).path (not the url[7:] strip used by the browser strategy), streams the file in chunks via aiofiles, and decodes as utf-8 with replacement. The existence check runs before any I/O starts.","triggerScenarios":"Running AsyncWebCrawler/AsyncHTTPCrawler with crawl(url='file:///no/such/file.html'). Note urlparse keeps percent-encoding: a URL with %20 spaces will fail the os.path.exists check unless the path is unquoted; also relative/Windows-style paths.","commonSituations":"Docker or CI environments where the file is not mounted; URLs built by hand with encoded characters; files removed between queue construction and crawl; sharing fixture paths across machines.","solutions":["Verify existence first with os.path.exists(urllib.parse.unquote(parsed.path)) and build the URL with Path.as_uri().","Mount or copy the file into the container/CI environment.","Percent-decode the URL path before checking when it may contain encoded characters.","Skip and log missing files when crawling a batch of file:// URLs."],"exampleFix":"// before\nawait crawler.crawler_strategy.crawl(\"file://data/report.html\")\n\n// after\nfrom pathlib import Path\nfrom urllib.parse import unquote, urlparse\npath = unquote(urlparse(file_url).path)\nif not os.path.exists(path):\n    raise FileNotFoundError(path)\nawait crawler.crawler_strategy.crawl(file_url)","handlingStrategy":"validation","validationCode":"import os\nfrom urllib.parse import urlparse, unquote\n\ndef file_url_exists(url: str) -> bool:\n    return os.path.isfile(unquote(urlparse(url).path))","typeGuard":null,"tryCatchPattern":"try:\n    resp = await crawler.crawler_strategy.crawl(file_url)\nexcept FileNotFoundError as e:\n    logger.warning(f\"skip missing file: {e}\")","preventionTips":["Use Path.as_uri() to build file URLs","Mount files into containers","Check existence right before crawl, not at queue-build time"],"tags":["local-file","http-crawler","filesystem","validation"],"backgroundTag":null,"analyzedSha":"7e801521428ee12509994d39151006f64055ebe3","analyzedAt":"2026-08-14T20:46:20.673Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}