langchain-ai/langchain · error · ValueError

Source node {source.id} not in graph

Error message

Source node {source.id} not in graph

What it means

`Graph.add_edge` requires that the source node's id already exists in the graph's node table; edges may only connect registered nodes. If `source.id` is not in `self.nodes`, `ValueError` is raised, since an edge pointing at a missing node would corrupt traversal.

Source

Thrown at libs/core/langchain_core/runnables/graph.py:376

        conditional: bool = False,  # noqa: FBT001,FBT002
    ) -> Edge:
        """Add an edge to the graph and return it.

        Args:
            source: The source node of the edge.
            target: The target node of the edge.
            data: Optional data associated with the edge.
            conditional: Whether the edge is conditional.

        Returns:
            The edge that was added to the graph.

        Raises:
            ValueError: If the source or target node is not in the graph.
        """
        if source.id not in self.nodes:
            msg = f"Source node {source.id} not in graph"
            raise ValueError(msg)
        if target.id not in self.nodes:
            msg = f"Target node {target.id} not in graph"
            raise ValueError(msg)
        edge = Edge(
            source=source.id, target=target.id, data=data, conditional=conditional
        )
        self.edges.append(edge)
        return edge

    def extend(
        self, graph: Graph, *, prefix: str = ""
    ) -> tuple[Node | None, Node | None]:
        """Add all nodes and edges from another graph.

        Note this doesn't check for duplicates, nor does it connect the graphs.

        Args:
            graph: The graph to add.

View on GitHub (pinned to e32fa9a52e)

Solutions

  1. Add both endpoint nodes (`add_node`) before calling `add_edge`.
  2. Reuse the exact `Node` objects returned by `add_node` when creating edges, rather than new Node instances.
  3. When merging graphs, use `Graph.extend(other, prefix=...))` (it wires nodes and edges consistently) instead of manual node/edge copying.

Example fix

# before
graph.add_edge(node_a, node_b)  # node_a not added yet

# after
na = graph.add_node(data=node_a)
nb = graph.add_node(data=node_b)
graph.add_edge(na, nb)
Defensive patterns

Strategy: validation

Validate before calling

assert source.id in graph.nodes and target.id in graph.nodes
graph.add_edge(source, target)

Prevention

When it happens

Trigger: Constructing `Edge`/`Node` objects manually and calling `add_edge(node_a, node_b)` before `add_node(node_a)`; using two distinct `Node` instances that conceptually share an id but where only one was added; copying edges from another graph without first extending the nodes.

Common situations: Hand-built graphs for `.get_graph()` overrides in custom Runnables; refactoring graph-building code so node insertion moved after edge creation; merging graphs where nodes were prefixed but the edge endpoints were not updated to the prefixed ids.

Related errors


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