langchain-ai/langgraph · error · ValueError

atee() requires n >= 1

Error message

atee() requires n >= 1

What it means

Guard clause at the top of StreamChannel.atee, the async fan-out helper. It validates the branch-count argument before creating any buffers or the shared asyncio.Lock: an n of 0 (or negative) would produce an empty tuple of iterators and silently detach the caller from the stream while the underlying cursor goes unconsumed, so it is rejected eagerly. The input at fault is the n parameter passed to atee(); the sync counterpart tee() enforces the same invariant.

Solutions

  1. Pass n >= 1 to atee()
  2. Use plain `async for` if only one consumer is needed
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at libs/langgraph/langgraph/stream/stream_channel.py:309 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of langchain-ai/langgraph@38031739e5 (2026-08-26). Data as JSON: /api/errors/620bc4ea6f2ca8f4. Report an issue: GitHub.

Appendix: source

Thrown at libs/langgraph/langgraph/stream/stream_channel.py:309

        Caller-driven fan-out: each branch's `__anext__` either pops
        from its own buffer or, under a shared `asyncio.Lock`, pulls
        one item from the underlying cursor and distributes it to
        every branch's buffer.

        Args:
            n: Number of branches to create. Must be >= 1.

        Returns:
            A tuple of `n` async iterators over the same underlying
            stream.

        Raises:
            TypeError: If the channel is unbound or bound to sync mode.
            RuntimeError: If the channel already has a subscriber.
            ValueError: If `n` < 1.
        """
        if n < 1:
            raise ValueError("atee() requires n >= 1")
        source = self.__aiter__()
        buffers: list[deque[T]] = [deque() for _ in range(n)]
        exhausted = [False]
        error: list[BaseException | None] = [None]
        lock = asyncio.Lock()

        async def branch(i: int) -> AsyncIterator[T]:
            buf = buffers[i]
            while True:
                if buf:
                    yield buf.popleft()
                    continue
                if exhausted[0]:
                    if error[0] is not None:
                        raise error[0]
                    return
                async with lock:
                    if buf or exhausted[0]:

View on GitHub (pinned to 38031739e5)