deepset-ai/haystack · error · ComponentError

{cls.__name__} must have a 'run()' method. See the docs for

Error message

{cls.__name__} must have a 'run()' method. See the docs for more information.

What it means

The @component class decorator validates a class's structure before registering it in the component registry. Every Haystack component must expose a 'run' method, since pipelines invoke it; a class lacking one fails this check with a ComponentError at decoration time.

Source

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

            setattr(  # noqa: B010
                run_method,
                "_output_types_cache",
                {name: OutputSocket(name=name, type=type_) for name, type_ in types.items()},
            )
            return run_method

        return output_types_decorator

    def _component(self, cls: type[T]) -> type[T]:
        """
        Decorator validating the structure of the component and registering it in the components registry.
        """
        logger.debug("Registering {component} as a component", component=cls)

        # Check for required methods and fail as soon as possible
        if not hasattr(cls, "run"):
            raise ComponentError(f"{cls.__name__} must have a 'run()' method. See the docs for more information.")

        def copy_class_namespace(namespace: dict[str, Any]) -> None:
            """
            This is the callback that `typing.new_class` will use to populate the newly created class.

            Simply copy the whole namespace from the decorated class.
            """
            for key, val in dict(cls.__dict__).items():
                # __dict__ and __weakref__ are class-bound, we should let Python recreate them.
                if key in ("__dict__", "__weakref__"):
                    continue
                namespace[key] = val

        # Recreate the decorated component class so it uses our metaclass.
        # We must explicitly redefine the type of the class to make sure language servers
        # and type checkers understand that the class is of the correct type.
        new_cls: type[T] = new_class(cls.__name__, cls.__bases__, {"metaclass": ComponentMeta}, copy_class_namespace)

View on GitHub (pinned to e318778c9b)

Solutions

  1. Add a 'run' method (and optionally 'run_async') to the class, decorated with @component.output_types if needed
  2. Check the method name spelling — it must be exactly 'run'
  3. If the class should not be a component, remove the @component decorator

Example fix

// before
@component
class MyComponent:
    def execute(self, x: int) -> dict: ...

// after
@component
class MyComponent:
    @component.output_types(int)
    def run(self, x: int) -> dict[str, int]: ...
Defensive patterns

Strategy: validation

Validate before calling

def validate_component(cls) -> None:
    if not callable(getattr(cls, "run", None)):
        raise TypeError(f"{cls.__name__} must define a 'run' method before @component is applied")

Type guard

def is_valid_component(cls) -> bool:
    return callable(getattr(cls, "run", None))

Try / catch

try:
    @component
    class C: ...
except ComponentError as e:
    logging.error("Component structure invalid: %s", e)

Prevention

When it happens

Trigger: Applying @component to a class that defines no 'run' method — e.g. the method is named differently (execute, __call__, run_async only with no run in older versions), or it is defined only dynamically/in a base class that's not actually inherited.

Common situations: Renaming 'run' during refactoring while keeping @component; wrapping the class with a metaclass or tool that strips methods; defining run as an instance attribute (self.run = ...) instead of a method; subclassing a Protocol instead of a concrete component.

Related errors


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