langchain-ai/langchain · error · ValueError

RunnableSequence must have at least {_RUNNABLE_SEQUENCE_MIN_

Error message

RunnableSequence must have at least {_RUNNABLE_SEQUENCE_MIN_STEPS} steps, got {len(steps_flat)}

What it means

`RunnableSequence.__init__` validates that a sequence contains at least `_RUNNABLE_SEQUENCE_MIN_STEPS` (2) steps after flattening nested `RunnableSequence`s and coercing callables. A sequence with 0 or 1 steps is meaningless (it is just the single runnable, or nothing), so the constructor rejects it with a `ValueError`. Flattening means nested sequences contribute their inner steps, so only the final flattened count matters.

Source

Thrown at libs/core/langchain_core/runnables/base.py:3190

            last: The last `Runnable` in the sequence.

        Raises:
            ValueError: If the sequence has less than 2 steps.
        """
        steps_flat: list[Runnable[Any, Any]] = []
        if not steps and first is not None and last is not None:
            steps_flat = [first] + (middle or []) + [last]
        for step in steps:
            if isinstance(step, RunnableSequence):
                steps_flat.extend(step.steps)
            else:
                steps_flat.append(coerce_to_runnable(step))
        if len(steps_flat) < _RUNNABLE_SEQUENCE_MIN_STEPS:
            msg = (
                f"RunnableSequence must have at least {_RUNNABLE_SEQUENCE_MIN_STEPS} "
                f"steps, got {len(steps_flat)}"
            )
            raise ValueError(msg)
        super().__init__(
            first=steps_flat[0],
            middle=list(steps_flat[1:-1]),
            last=steps_flat[-1],
            name=name,
        )

    @classmethod
    @override
    def get_lc_namespace(cls) -> list[str]:
        """Get the namespace of the LangChain object.

        Returns:
            `["langchain", "schema", "runnable"]`
        """
        return ["langchain", "schema", "runnable"]

    @property

View on GitHub (pinned to e32fa9a52e)

Solutions

  1. Pass at least two runnables: `RunnableSequence(step_a, step_b)`.
  2. If you have exactly one runnable, use it directly instead of wrapping it in a sequence (or `coerce_to_runnable(x)` for callables).
  3. Guard dynamic construction: `RunnableSequence(*steps) if len(steps) >= 2 else coerce_to_runnable(steps[0])`.
  4. Prefer the pipe operator `a | b`, which never builds an under-sized sequence.

Example fix

// before
seq = RunnableSequence(my_single_runnable)

// after
seq = my_single_runnable  # a single step needs no sequence
# or, for two steps:
seq = RunnableSequence(step_a, step_b)
// dynamic list:
seq = RunnableSequence(*steps) if len(steps) >= 2 else coerce_to_runnable(steps[0])
Defensive patterns

Strategy: validation

Validate before calling

from langchain_core.runnables import RunnableSequence, Runnable, coerce_to_runnable

def build_sequence(steps: list) -> Runnable:
    if len(steps) >= 2:
        return RunnableSequence(*steps)
    if len(steps) == 1:
        return coerce_to_runnable(steps[0])
    msg = 'steps list is empty'
    raise ValueError(msg)

Type guard

from langchain_core.runnables import Runnable, RunnableSequence

def is_valid_sequence(steps: list[Runnable]) -> bool:
    return len(steps) >= 2

Try / catch

try:
    seq = RunnableSequence(*steps)
except ValueError as e:
    if 'at least' in str(e):
        seq = coerce_to_runnable(steps[0]) if steps else None
    else:
        raise

Prevention

When it happens

Trigger: Calling `RunnableSequence()` with no args; `RunnableSequence(my_runnable)` with a single step; passing `steps=[x]`, or `first=x` without a `last`; constructing with `steps` where nesting still flattens to fewer than 2 steps (e.g. one nested single-step sequence).

Common situations: Programmatically building sequences from dynamic lists (`RunnableSequence(*fns)` where `fns` may have 0 or 1 element); refactoring the `|` operator pipeline into explicit `RunnableSequence` calls; wrapping user-supplied step lists at runtime.

Related errors


AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14). Data as JSON: /api/errors/17c6b3a01e323a59. Report an issue: GitHub.