{"record":{"id":"aec118789ec6b6da","repo":"deepset-ai/haystack","slug":"method-run-async-of-component-cls-name-m","errorCode":null,"errorMessage":"Method 'run_async' of component '{cls.__name__}' must be a coroutine","messagePattern":"Method 'run_async' of component '(.+?)' must be a coroutine","errorType":"exception","errorClass":"ComponentError","httpStatus":null,"severity":"error","filePath":"haystack/core/component/component.py","lineNumber":310,"sourceCode":"            instance = super().__call__(*args, **kwargs)\n        else:\n            try:\n                pre_init_hook.in_progress = True\n                named_positional_args = ComponentMeta._positional_to_kwargs(cls, args)\n                assert set(named_positional_args.keys()).intersection(kwargs.keys()) == set(), (\n                    \"positional and keyword arguments overlap\"\n                )\n                kwargs.update(named_positional_args)\n                pre_init_hook.callback(cls, kwargs)\n                instance = super().__call__(**kwargs)\n            finally:\n                pre_init_hook.in_progress = False\n\n        # Before returning, we have the chance to modify the newly created\n        # Component instance, so we take the chance and set up the I/O sockets\n        has_async_run = hasattr(instance, \"run_async\")\n        if has_async_run and not inspect.iscoroutinefunction(instance.run_async):\n            raise ComponentError(f\"Method 'run_async' of component '{cls.__name__}' must be a coroutine\")\n        instance.__haystack_supports_async__ = has_async_run\n\n        ComponentMeta._parse_and_set_input_sockets(cls, instance)\n        ComponentMeta._parse_and_set_output_sockets(instance)\n\n        # Since a Component can't be used in multiple Pipelines at the same time\n        # we need to know if it's already owned by a Pipeline when adding it to one.\n        # We use this flag to check that.\n        instance.__haystack_added_to_pipeline__ = None\n\n        return instance\n\n\ndef _component_repr(component: Component) -> str:\n    \"\"\"\n    All Components override their __repr__ method with this one.\n\n    It prints the component name and the input/output sockets.","sourceCodeStart":292,"sourceCodeEnd":328,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/core/component/component.py#L292-L328","documentation":"When a component class is instantiated, ComponentMeta.__call__ checks that run_async (if defined) is an async coroutine function via inspect.iscoroutinefunction. A plain (non-async) run_async method raises ComponentError because Haystack pipelines await run_async in async pipelines.","triggerScenarios":"Defining `def run_async(...)` without `async def` on a class decorated with @component while also having a run method; wrapping run_async with a non-async decorator that loses coroutine-ness (e.g. functools.wraps over a sync wrapper, some middleware/decorators); assigning a sync bound function to instance.run_async.","commonSituations":"Copy-pasting sync run into run_async but forgetting the async keyword; applying a custom decorator to run_async that returns a plain function; migrating code where run_async was previously sync-tolerated.","solutions":["Change `def run_async` to `async def run_async`","If a decorator wraps run_async, ensure the wrapper preserves the coroutine (use functools.wraps on an async wrapper or return the coroutine function)","If async is not needed, remove run_async and keep only run"],"exampleFix":"# before\nclass Echo:\n    @component.output_types(out=str)\n    def run(self, x: str):\n        return {\"out\": x}\n    def run_async(self, x: str):  # not a coroutine\n        return self.run(x)\n\n# after\nclass Echo:\n    @component.output_types(out=str)\n    def run(self, x: str):\n        return {\"out\": x}\n    @component.output_types(out=str)\n    async def run_async(self, x: str):\n        return {\"out\": x}","handlingStrategy":"validation","validationCode":"import inspect\nif hasattr(MyComponent, \"run_async\") and not inspect.iscoroutinefunction(MyComponent.run_async):\n    raise TypeError(\"run_async must be declared with async def\")","typeGuard":"def is_valid_async_component(instance) -> bool:\n    ra = getattr(instance, \"run_async\", None)\n    return ra is None or inspect.iscoroutinefunction(ra)","tryCatchPattern":"try:\n    comp = MyComponent()\nexcept ComponentError as e:\n    if \"must be a coroutine\" in str(e):\n        logging.error(\"Declare run_async with 'async def'\")\n    raise","preventionTips":["Always write run_async with the async def keyword","Check any custom decorators applied to run_async preserve coroutine-ness (test with inspect.iscoroutinefunction)","Prefer deriving run_async automatically from run via a helper that produces an async wrapper"],"tags":["python","haystack","component","async","coroutine"],"backgroundTag":"async-method-must-be-coroutine","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}