deepset-ai/haystack · error · ComponentError
Output type specifications of 'run' and 'run_async' methods
Error message
Output type specifications of 'run' and 'run_async' methods must be the same
What it means
When a component defines both run and run_async, Haystack compares the cached @component.output_types specs of the two methods at instantiation time. They must be identical because the component's output sockets are shared by both entry points. Mismatched or missing decorations on one method trigger this ComponentError.
Source
Thrown at haystack/core/component/component.py:226
def _parse_and_set_output_sockets(instance: Any) -> None:
has_async_run = hasattr(instance, "run_async")
# If `component.set_output_types()` was called in the component constructor,
# `__haystack_output__` is already populated, no need to do anything.
if not hasattr(instance, "__haystack_output__"):
# If that's not the case, we need to populate `__haystack_output__`
#
# If either of the run methods were decorated, they'll have a field assigned that
# stores the output specification. If both run methods were decorated, we ensure that
# outputs are the same. We deepcopy the content of the cache to transfer ownership from
# the class method to the actual instance, so that different instances of the same class
# won't share this data.
run_output_types = getattr(instance.run, "_output_types_cache", {})
async_run_output_types = getattr(instance.run_async, "_output_types_cache", {}) if has_async_run else {}
if has_async_run and run_output_types != async_run_output_types:
raise ComponentError("Output type specifications of 'run' and 'run_async' methods must be the same")
output_types_cache = run_output_types
instance.__haystack_output__ = Sockets(instance, deepcopy(output_types_cache), OutputSocket)
@staticmethod
def _parse_and_set_input_sockets(component_cls: type, instance: Any) -> None:
def inner(method: Callable[..., Any], sockets: Sockets) -> inspect.Signature:
from inspect import Parameter
run_signature = inspect.signature(method)
# Resolves the annotations of components using postponed evaluation of annotations, where they are stored
# as strings.
param_types = _resolve_parameter_types(method)
for param_name, param_info in run_signature.parameters.items():
if param_name == "self" or param_info.kind in (Parameter.VAR_POSITIONAL, Parameter.VAR_KEYWORD):
continue
View on GitHub (pinned to e318778c9b)
Solutions
- Apply the identical @component.output_types(...) decorator to both run and run_async.
- If the outputs differ semantically, split into two components rather than sharing run/run_async.
- Check for typos in keys/types: the comparison is dict equality, so 'reply' vs 'response' or int vs str mismatches all fail.
- Alternatively, call component.set_output_types(...) in the constructor with the same spec, which bypasses the per-method caches.
Example fix
// before @component.output_types(reply=str) def run(self, q: str): ... @component.output_types(answer=str) async def run_async(self, q: str): ... // after @component.output_types(reply=str) def run(self, q: str): ... @component.output_types(reply=str) async def run_async(self, q: str): ...
Defensive patterns
Strategy: validation
Validate before calling
from dataclasses import replace
run_spec = getattr(MyComponent.run, "_output_types_cache", {})
async_spec = getattr(MyComponent.run_async, "_output_types_cache", {})
assert run_spec == async_spec, f"output_types mismatch: {run_spec} vs {async_spec}" Try / catch
try:
comp = MyComponent()
except ComponentError as e:
if "Output type specifications" in str(e):
raise RuntimeError("Decorate run and run_async with identical @component.output_types") from e Prevention
- Copy the @component.output_types decorator line verbatim to both methods
- When refactoring outputs, grep for all output_types decorators in the class
- Consider set_output_types in __init__ as a single source of truth
- Instantiate components in tests at import time to catch decorator drift early
When it happens
Trigger: Defining run with @component.output_types(...) but run_async with a different (or no) output_types decoration; run_async decorated with different keys/types (e.g. run returns {'a': int} but run_async returns {'a': str}); one method's cache is empty because the decorator wasn't applied at all.
Common situations: Adding run_async to an existing component later and forgetting to mirror the decorators; copy-paste editing one method's output types without the other; refactoring renaming an output key in only one method.
Related errors
- Pre-init hooks do not support components with variadic posit
- set_input_types()/set_input_type() cannot override the param
- Cannot call `set_output_types` on a component that already h
- Parameters of 'run' and 'run_async' methods must be the same
- Method 'run_async' of component '{cls.__name__}' must be a c
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/559ac632b67e678c.
Report an issue: GitHub.