{"record":{"id":"d85bfe74c412370a","repo":"deepset-ai/haystack","slug":"parameters-of-run-and-run-async-methods-must-b","errorCode":null,"errorMessage":"Parameters of 'run' and 'run_async' methods must be the same.\nDifferences found:\n{sig_diff}","messagePattern":"Parameters of 'run' and 'run_async' methods must be the same\\.\nDifferences found:\n(.+?)","errorType":"exception","errorClass":"ComponentError","httpStatus":null,"severity":"error","filePath":"haystack/core/component/component.py","lineNumber":281,"sourceCode":"        if not hasattr(instance, \"__haystack_input__\"):\n            instance.__haystack_input__ = Sockets(instance, {}, InputSocket)\n\n        inner(getattr(component_cls, \"run\"), instance.__haystack_input__)  # noqa: B009\n\n        # Ensure that the sockets are the same for the async method, if it exists.\n        async_run = getattr(component_cls, \"run_async\", None)\n        if async_run is not None:\n            run_sockets = Sockets(instance, {}, InputSocket)\n            async_run_sockets = Sockets(instance, {}, InputSocket)\n\n            # Can't use the sockets from above as they might contain\n            # values set with set_input_types().\n            run_sig = inner(getattr(component_cls, \"run\"), run_sockets)  # noqa: B009\n            async_run_sig = inner(async_run, async_run_sockets)\n\n            if async_run_sockets != run_sockets or run_sig != async_run_sig:\n                sig_diff = _compare_run_methods_signatures(run_sig, async_run_sig)\n                raise ComponentError(\n                    f\"Parameters of 'run' and 'run_async' methods must be the same.\\nDifferences found:\\n{sig_diff}\"\n                )\n\n    def __call__(cls, *args: Any, **kwargs: Any) -> Any:\n        \"\"\"\n        This method is called when clients instantiate a Component and runs before __new__ and __init__.\n        \"\"\"\n        # This will call __new__ then __init__, giving us back the Component instance\n        pre_init_hook = _COMPONENT_PRE_INIT_HOOK.get()\n        if pre_init_hook is None or pre_init_hook.in_progress:\n            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                )","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/core/component/component.py#L263-L299","documentation":"ComponentMeta validates that a component's 'run' and 'run_async' methods declare exactly the same parameters (and matching input sockets). If they diverge, class instantiation raises ComponentError with a signature diff. Haystack requires both so sync and async pipeline execution behave identically.","triggerScenarios":"Defining a component class where run and run_async have different parameter names, different type annotations, different defaults, or different sets of parameters; only run is decorated with @component.input_types while run_async is not (or vice versa), producing mismatched sockets.","commonSituations":"Adding or renaming a parameter in run but forgetting run_async; decorating only one of the two methods with the input_types decorator; hand-writing run_async instead of using a helper that mirrors run.","solutions":["Make run_async declare exactly the same parameters, annotations, and defaults as run","Apply the same @component.input_types / set_input_types configuration to both methods","Read the sig_diff in the message to see which parameter differs, then fix that parameter in the offending method","If async support is not needed, delete run_async entirely (then only run is validated)"],"exampleFix":"# before\nclass Sum:\n    def run(self, a: int, b: int = 0):\n        return {\"result\": a + b}\n    async def run_async(self, a: int):  # missing b, default differs\n        return {\"result\": a}\n\n# after\nclass Sum:\n    def run(self, a: int, b: int = 0):\n        return {\"result\": a + b}\n    async def run_async(self, a: int, b: int = 0):\n        return {\"result\": a + b}","handlingStrategy":"validation","validationCode":"import inspect\ndef validate_run_signatures(cls):\n    run, run_async = getattr(cls, \"run\", None), getattr(cls, \"run_async\", None)\n    if run and run_async:\n        rs, asig = inspect.signature(run), inspect.signature(run_async)\n        if rs.parameters != asig.parameters:\n            raise ValueError(f\"run/run_async mismatch: {rs} vs {asig}\")","typeGuard":"def has_matching_signatures(cls) -> bool:\n    r, ra = getattr(cls, \"run\", None), getattr(cls, \"run_async\", None)\n    return not (r and ra) or inspect.signature(r).parameters == inspect.signature(ra).parameters","tryCatchPattern":null,"preventionTips":["Always define run_async as an exact mirror of run (same names, annotations, defaults)","Decorate both run and run_async with the same input_types decorator arguments","Write a unit test that compares inspect.signature(run) and inspect.signature(run_async) for every component"],"tags":["python","haystack","component","async","signature-mismatch"],"backgroundTag":"component-run-signature-mismatch","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}