deepset-ai/haystack · error · ComponentError

Cannot call `set_output_types` on a component that already h

Error message

Cannot call `set_output_types` on a component that already has the 'output_types' decorator on its `run` or `run_async` methods.

What it means

If run (or run_async) is already decorated with @component.output_types, the output sockets are fixed by the decorator and must not be overridden. Calling component.set_output_types() on such an instance raises ComponentError to prevent silently conflicting output definitions.

Source

Thrown at haystack/core/component/component.py:516

        class MyComponent:

            def __init__(self, value: int) -> None:
                component.set_output_types(self, output_1=int, output_2=str)
                ...

            # no decorators here
            def run(self, value: int):
                return {"output_1": 1, "output_2": "2"}

            # also no decorators here
            async def run_async(self, value: int):
                return {"output_1": 1, "output_2": "2"}
        ```
        """
        has_run_decorator = hasattr(instance.run, "_output_types_cache")
        has_run_async_decorator = hasattr(instance, "run_async") and hasattr(instance.run_async, "_output_types_cache")
        if has_run_decorator or has_run_async_decorator:
            raise ComponentError(
                "Cannot call `set_output_types` on a component that already has the 'output_types' decorator on its "
                "`run` or `run_async` methods."
            )

        instance.__haystack_output__ = Sockets(
            instance, {name: OutputSocket(name=name, type=type_) for name, type_ in types.items()}, OutputSocket
        )

    def output_types(
        self, **types: Any
    ) -> Callable[[Callable[RunParamsT, RunReturnT]], Callable[RunParamsT, RunReturnT]]:
        """
        Decorator factory that specifies the output types of a component.

        Use as:
        ```python
        @component
        class MyComponent:

View on GitHub (pinned to e318778c9b)

Solutions

  1. Remove the @component.output_types decorator from run/run_async if you want to set outputs imperatively via set_output_types
  2. Remove the set_output_types call and rely on the decorator's output definition instead
  3. Merge the desired outputs into the decorator's argument list rather than calling set_output_types

Example fix

# before
class C:
    @component.output_types(out=str)
    def run(self, x: int):
        return {"out": str(x)}

set_output_types(C(), {"out": int, "extra": bool})  # raises

# after
class C:
    @component.output_types(out=int, extra=bool)
    def run(self, x: int):
        return {"out": x, "extra": True}
Defensive patterns

Strategy: validation

Validate before calling

def can_set_output_types(comp) -> bool:
    return not hasattr(comp.run, "_output_types_cache") and not (
        hasattr(comp, "run_async") and hasattr(comp.run_async, "_output_types_cache")
    )

Type guard

def lacks_output_types_decorator(comp) -> bool:
    run_async = getattr(comp, "run_async", None)
    return (
        not hasattr(comp.run, "_output_types_cache")
        and (run_async is None or not hasattr(run_async, "_output_types_cache"))
    )

Try / catch

try:
    set_output_types(comp, {"out": int})
except ComponentError as e:
    logging.error("Remove @component.output_types decorator or the set_output_types call")
    raise

Prevention

When it happens

Trigger: Calling set_output_types(instance, {...}) on a component whose run method has _output_types_cache (applied by @component.output_types) or whose run_async has it.

Common situations: Mixing the decorator-based and imperative APIs to configure the same component; subclassing a decorated component and trying to change outputs at runtime; copy-pasting set_output_types code into a component that already uses the decorator.

Related errors


AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30). Data as JSON: /api/errors/59f0985100e4fbfe. Report an issue: GitHub.