deepset-ai/haystack · error · ComponentError
Parameters of 'run' and 'run_async' methods must be the same
Error message
Parameters of 'run' and 'run_async' methods must be the same.
Differences found:
{sig_diff} What it means
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.
Source
Thrown at haystack/core/component/component.py:281
if not hasattr(instance, "__haystack_input__"):
instance.__haystack_input__ = Sockets(instance, {}, InputSocket)
inner(getattr(component_cls, "run"), instance.__haystack_input__) # noqa: B009
# Ensure that the sockets are the same for the async method, if it exists.
async_run = getattr(component_cls, "run_async", None)
if async_run is not None:
run_sockets = Sockets(instance, {}, InputSocket)
async_run_sockets = Sockets(instance, {}, InputSocket)
# Can't use the sockets from above as they might contain
# values set with set_input_types().
run_sig = inner(getattr(component_cls, "run"), run_sockets) # noqa: B009
async_run_sig = inner(async_run, async_run_sockets)
if async_run_sockets != run_sockets or run_sig != async_run_sig:
sig_diff = _compare_run_methods_signatures(run_sig, async_run_sig)
raise ComponentError(
f"Parameters of 'run' and 'run_async' methods must be the same.\nDifferences found:\n{sig_diff}"
)
def __call__(cls, *args: Any, **kwargs: Any) -> Any:
"""
This method is called when clients instantiate a Component and runs before __new__ and __init__.
"""
# This will call __new__ then __init__, giving us back the Component instance
pre_init_hook = _COMPONENT_PRE_INIT_HOOK.get()
if pre_init_hook is None or pre_init_hook.in_progress:
instance = super().__call__(*args, **kwargs)
else:
try:
pre_init_hook.in_progress = True
named_positional_args = ComponentMeta._positional_to_kwargs(cls, args)
assert set(named_positional_args.keys()).intersection(kwargs.keys()) == set(), (
"positional and keyword arguments overlap"
)View on GitHub (pinned to e318778c9b)
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)
Example fix
# before
class Sum:
def run(self, a: int, b: int = 0):
return {"result": a + b}
async def run_async(self, a: int): # missing b, default differs
return {"result": a}
# after
class Sum:
def run(self, a: int, b: int = 0):
return {"result": a + b}
async def run_async(self, a: int, b: int = 0):
return {"result": a + b} Defensive patterns
Strategy: validation
Validate before calling
import inspect
def validate_run_signatures(cls):
run, run_async = getattr(cls, "run", None), getattr(cls, "run_async", None)
if run and run_async:
rs, asig = inspect.signature(run), inspect.signature(run_async)
if rs.parameters != asig.parameters:
raise ValueError(f"run/run_async mismatch: {rs} vs {asig}") Type guard
def has_matching_signatures(cls) -> bool:
r, ra = getattr(cls, "run", None), getattr(cls, "run_async", None)
return not (r and ra) or inspect.signature(r).parameters == inspect.signature(ra).parameters Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Method 'run_async' of component '{cls.__name__}' must be a c
- Cannot set input types on a component that doesn't have a kw
- Cannot call `set_output_types` on a component that already h
- 'output_types' decorator can only be used on 'run' and 'run_
- {cls.__name__} must have a 'run()' method. See the docs for
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/d85bfe74c412370a.
Report an issue: GitHub.