deepset-ai/haystack · error · PipelineRuntimeError

PipelineRuntimeError.from_invalid_output(component_name, ins

Error message

PipelineRuntimeError.from_invalid_output(component_name, instance.__class__, component_output)

What it means

Haystack requires every component to return a Mapping (dict-like) output so results can be routed to other components. If a component's run() returns a non-mapping (list, string, None, object), PipelineRuntimeError.from_invalid_output is raised naming the component and its class.

Source

Thrown at haystack/core/pipeline/pipeline.py:190

                # This is important when Agent components internally use Pipeline._run_component
                # and trigger breakpoints that need to bubble up to the main pipeline
                raise error

            # Any components that internally use Pipeline._run_component could raise a PipelineRuntimeError with
            # additional context (e.g. Agent raises an agent snapshot) so we re-raise here instead of wrapping it in
            # another PipelineRuntimeError

            except PipelineRuntimeError as runtime_error:
                raise runtime_error

            # Catch all other exceptions and wrap them in a PipelineRuntimeError
            except Exception as error:
                raise PipelineRuntimeError.from_exception(component_name, instance.__class__, error) from error

            component_visits[component_name] += 1

            if not isinstance(component_output, Mapping):
                raise PipelineRuntimeError.from_invalid_output(component_name, instance.__class__, component_output)

            _validate_component_output_keys(component_name, component, component_output)

            span.set_tag(_COMPONENT_VISITS, component_visits[component_name])
            span.set_content_tag(_COMPONENT_OUTPUT, component_output)

            return component_output

    @mark_deserialization_internal
    def run(  # noqa: PLR0915, PLR0912, C901
        self,
        data: dict[str, Any],
        include_outputs_from: set[str] | None = None,
        *,
        break_point: Breakpoint | None = None,
        pipeline_snapshot: PipelineSnapshot | None = None,
        snapshot_callback: SnapshotCallback | None = None,
    ) -> dict[str, Any]:

View on GitHub (pinned to e318778c9b)

Solutions

  1. Make run() return a dict keyed by the component's declared output sockets, e.g. {"documents": docs}
  2. Check the @component decorator output type declarations match the returned dict keys
  3. Wrap third-party callables to convert their results into a dict

Example fix

// before
def run(self, docs):
    return docs
// after
def run(self, docs):
    return {"documents": docs}
Defensive patterns

Strategy: validation

Validate before calling

out = my_component.run(documents=docs)
if not isinstance(out, Mapping):
    raise TypeError("run() must return a dict keyed by output sockets")

Type guard

from collections.abc import Mapping
def returns_mapping(out) -> bool:
    return isinstance(out, Mapping)

Try / catch

from haystack.core.errors import PipelineRuntimeError
try:
    result = pipeline.run(inputs)
except PipelineRuntimeError as e:
    if "invalid output" in str(e).lower():
        logger.error("Fix component run() to return a dict: %s", e)
    else:
        raise

Prevention

When it happens

Trigger: A custom component whose run() returns e.g. ["a", "b"], "text", or None instead of {"output": ...}; a mis-wrapped component from another framework.

Common situations: Hand-written components returning bare values, refactored components whose return type changed, third-party components not adapted to Haystack's Component contract.

Related errors


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