ScrapeGraphAI/Scrapegraph-ai · error · ValueError

ConditionalNode '{node.node_name}' must have exactly two out

Error message

ConditionalNode '{node.node_name}' must have exactly two outgoing edges.

What it means

BaseGraph._set_conditional_node_edges validates that every node whose node_type is 'conditional_node' has exactly two outgoing raw edges (the true branch and the false branch). Any other out-degree (0, 1, 3+ edges) raises this during graph construction in __init__.

Source

Thrown at scrapegraphai/graphs/base_graph.py:112

        edge_dict = {}
        for from_node, to_node in edges:
            if from_node.node_type != "conditional_node":
                edge_dict[from_node.node_name] = to_node.node_name
        return edge_dict

    def _set_conditional_node_edges(self):
        """
        Sets the true_node_name and false_node_name for each ConditionalNode.
        """
        for node in self.nodes:
            if node.node_type == "conditional_node":
                outgoing_edges = [
                    (from_node, to_node)
                    for from_node, to_node in self.raw_edges
                    if from_node.node_name == node.node_name
                ]
                if len(outgoing_edges) != 2:
                    raise ValueError(
                        f"ConditionalNode '{node.node_name}' must have exactly two outgoing edges."
                    )
                node.true_node_name = outgoing_edges[0][1].node_name
                try:
                    node.false_node_name = outgoing_edges[1][1].node_name
                except (IndexError, AttributeError) as e:
                    # IndexError: If outgoing_edges[1] doesn't exist
                    # AttributeError: If to_node is None or doesn't have node_name
                    node.false_node_name = None
                    raise ValueError(
                        f"Failed to set false_node_name for ConditionalNode '{node.node_name}'"
                    ) from e

    def _get_node_by_name(self, node_name: str):
        """Returns a node instance by its name."""
        return next(node for node in self.nodes if node.node_name == node_name)

    def _update_source_info(self, current_node, state):

View on GitHub (pinned to 532dfffbf6)

Solutions

  1. Ensure the conditional node has exactly two (from_node=conditional, to_node=...) entries in the edges list — one for true, one for false.
  2. Route any extra downstream nodes off the branch targets instead of off the conditional node itself.
  3. If you intended a single successor, use a normal 'node' type instead of 'conditional_node'.

Example fix

# before
graph = BaseGraph(nodes=[cond, a], edges=[(cond, a)])  # cond is conditional_node

# after
graph = BaseGraph(nodes=[cond, a, b], edges=[(cond, a), (cond, b)])
Defensive patterns

Strategy: validation

Validate before calling

from collections import Counter
out_deg = Counter(f.node_name for f, t in edges if getattr(f, 'node_type', '') == 'conditional_node')
for name, deg in out_deg.items():
    assert deg == 2, f'conditional node {name} has {deg} outgoing edges, needs exactly 2'

Type guard

def conditional_edges_valid(nodes, edges) -> bool:
    from collections import Counter
    cond = {n.node_name for n in nodes if n.node_type == 'conditional_node'}
    c = Counter(f.node_name for f, _ in edges if f.node_name in cond)
    return all(c[n] == 2 for n in cond)

Try / catch

try:
    g = BaseGraph(nodes=nodes, edges=edges, entry_point=entry)
except ValueError as e:
    if 'exactly two outgoing edges' in str(e):
        # fix edges list and retry
        raise
    raise

Prevention

When it happens

Trigger: Defining a BaseGraph whose edges list contains a conditional node with only one outgoing edge, three outgoing edges, or none; or connecting additional nodes to an existing conditional node before passing the edges to BaseGraph.

Common situations: Hand-building custom graphs (custom integrations, agent pipelines) and forgetting the false branch; refactoring a graph and accidentally adding a monitoring/cleanup edge off the conditional node; copying an example and deleting one edge.

Related errors


AI-assisted analysis of ScrapeGraphAI/Scrapegraph-ai@532dfffbf6 (2026-08-28). Data as JSON: /api/errors/94a37a8ac1ebd8bc. Report an issue: GitHub.