{"record":{"id":"52b3a07602683f85","repo":"unclecode/crawl4ai","slug":"self-class-name-object-has-no-attribute-52b3a0","errorCode":null,"errorMessage":"{self.__class__.__name__} object has no attribute '{attr}'","messagePattern":"(.+?) object has no attribute '(.+?)'","errorType":"exception","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"crawl4ai/models.py:315","lineNumber":5504,"sourceCode":"        if isinstance(results, list):\n            self._results = results\n        else:\n            self._results = [results]\n\n    def __iter__(self):\n        return iter(self._results)\n\n    def __getitem__(self, index):\n        return self._results[index]\n\n    def __len__(self):\n        return len(self._results)\n\n    def __getattr__(self, attr):\n        # Delegate attribute access to the first element.\n        if self._results:\n            return getattr(self._results[0], attr)\n        raise AttributeError(f\"{self.__class__.__name__} object has no attribute '{attr}'\")\n\n    def __repr__(self):\n        return f\"{self.__class__.__name__}({self._results!r})\"\n\nRunManyReturn = Union[\n    CrawlResultContainer[CrawlResultT],\n    AsyncGenerator[CrawlResultT, None]\n]\n\n\n# END of backward compatibility code for markdown/markdown_v2.\n# When removing this code in the future, make sure to:\n# 1. Replace the private attribute and property with a standard field\n# 2. Update any serialization logic that might depend on the current behavior\n\nclass AsyncCrawlResponse(BaseModel):\n    html: str\n    response_headers: Dict[str, str]","sourceCodeStart":5486,"sourceCodeEnd":5522,"githubUrl":"https://github.com/unclecode/crawl4ai/blob/7e801521428ee12509994d39151006f64055ebe3/deploy/docker/c4ai-code-context.md#L5486-L5522","documentation":"CrawlResultContainer wraps a list of CrawlResult objects (used by arun_many and by the markdown backward-compat layer) and delegates unknown attribute access to its first element. When the container is empty, there is nothing to delegate to, so __getattr__ raises AttributeError naming the container class and the missing attribute.","triggerScenarios":"Calling crawler.arun_many(urls, ...) where every crawl fails or the list is empty, then accessing result.url / result.markdown / any CrawlResult attribute on the container; accessing any attribute on a CrawlResultContainer built with no results.","commonSituations":"Assuming arun_many returns a single CrawlResult rather than a container; seed URL lists that are empty after dedup/validation; all crawls erroring out but the code proceeding to read attributes; also triggered incidentally when the deprecated-property tombstones (markdown_v2 etc.) are accessed through an empty container.","solutions":["Treat the return of arun_many as a collection: check len(result) or iterate for r in result before accessing fields","Log and inspect why zero results were produced (bad URLs, all crawls failed, empty input list)","If you expected a single result, use crawler.arun(url) instead of arun_many, or index results[0] after checking length"],"exampleFix":"// before\nprint(result.markdown)  # AttributeError when container is empty\n// after\nresults = await crawler.arun_many(urls, config=config)\nfor r in results:\n    print(r.url, r.markdown.raw_markdown)\n","handlingStrategy":"validation","validationCode":"results = await crawler.arun_many(urls, config=run_config)\nif len(results) == 0:\n    logger.warning(\"no crawl results produced; check input URLs and crawl errors\")\n    return []\nfirst = results[0]","typeGuard":"from crawl4ai import CrawlResultContainer, CrawlResult\n\ndef as_result_list(container):\n    if isinstance(container, CrawlResultContainer):\n        return list(container)\n    return [container] if isinstance(container, CrawlResult) else []","tryCatchPattern":"try:\n    url = results.url\nexcept AttributeError:\n    # container had zero results; fall back to iterating/inspecting failures\n    for r in results:\n        ...  # empty; investigate crawl failures instead\n    raise","preventionTips":["Never access CrawlResult attributes on an arun_many return without checking len() first","Validate and dedupe the seed URL list before crawling","Inspect each result's success/status_code fields rather than assuming all crawls succeeded"],"tags":["crawl4ai","arun-many","empty-result","crawl-result-container"],"backgroundTag":null,"analyzedSha":"7e801521428ee12509994d39151006f64055ebe3","analyzedAt":"2026-08-14T20:46:20.673Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}