unclecode/crawl4ai · error · TypeError

.run must be async

Error message

{cls.__name__}.run must be async

What it means

Error "{cls.__name__}.run must be async" thrown in unclecode/crawl4ai.

Solutions

  1. Declare the run method with async def so it can be awaited by the hub.
  2. Remove blocking synchronous calls from run or wrap them with asyncio.to_thread.

Example fix

async def run(self, url: str, **kwargs): ...

When it happens

Trigger: Thrown at crawl4ai/hub.py:35 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14). Data as JSON: /api/errors/6cdb14ab5b5ae1e3. Report an issue: GitHub.

Appendix: source

Thrown at crawl4ai/hub.py:35

    async def run(self, url: str = "", **kwargs) -> str:
        """
        Implement this method to return JSON string.
        Must accept URL + arbitrary kwargs for flexibility.
        """
        pass

    def __init_subclass__(cls, **kwargs):
        """Enforce interface validation on subclassing"""
        super().__init_subclass__(**kwargs)
        
        # Verify run method signature
        run_method = cls.run
        if not run_method.__code__.co_argcount >= 2:  # self + url
            raise TypeError(f"{cls.__name__} must implement 'run(self, url: str, **kwargs)'")
            
        # Verify async nature
        if not inspect.iscoroutinefunction(run_method):
            raise TypeError(f"{cls.__name__}.run must be async")

class CrawlerHub:
    _crawlers: Dict[str, Type[BaseCrawler]] = {}

    @classmethod
    def _discover_crawlers(cls):
        """Dynamically load crawlers from /crawlers in 3 lines"""
        base_path = Path(__file__).parent / "crawlers"
        for crawler_dir in base_path.iterdir():
            if crawler_dir.is_dir():
                try:
                    module = importlib.import_module(
                        f"crawl4ai.crawlers.{crawler_dir.name}.crawler"
                    )
                    for attr in dir(module):
                        cls._maybe_register_crawler(
                            getattr(module, attr), crawler_dir.name
                        )

View on GitHub (pinned to 7e80152142)