{"record":{"id":"94a37a8ac1ebd8bc","repo":"ScrapeGraphAI/Scrapegraph-ai","slug":"conditionalnode-node-node-name-must-have-exact","errorCode":null,"errorMessage":"ConditionalNode '{node.node_name}' must have exactly two outgoing edges.","messagePattern":"ConditionalNode '(.+?)' must have exactly two outgoing edges\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"scrapegraphai/graphs/base_graph.py","lineNumber":112,"sourceCode":"        edge_dict = {}\n        for from_node, to_node in edges:\n            if from_node.node_type != \"conditional_node\":\n                edge_dict[from_node.node_name] = to_node.node_name\n        return edge_dict\n\n    def _set_conditional_node_edges(self):\n        \"\"\"\n        Sets the true_node_name and false_node_name for each ConditionalNode.\n        \"\"\"\n        for node in self.nodes:\n            if node.node_type == \"conditional_node\":\n                outgoing_edges = [\n                    (from_node, to_node)\n                    for from_node, to_node in self.raw_edges\n                    if from_node.node_name == node.node_name\n                ]\n                if len(outgoing_edges) != 2:\n                    raise ValueError(\n                        f\"ConditionalNode '{node.node_name}' must have exactly two outgoing edges.\"\n                    )\n                node.true_node_name = outgoing_edges[0][1].node_name\n                try:\n                    node.false_node_name = outgoing_edges[1][1].node_name\n                except (IndexError, AttributeError) as e:\n                    # IndexError: If outgoing_edges[1] doesn't exist\n                    # AttributeError: If to_node is None or doesn't have node_name\n                    node.false_node_name = None\n                    raise ValueError(\n                        f\"Failed to set false_node_name for ConditionalNode '{node.node_name}'\"\n                    ) from e\n\n    def _get_node_by_name(self, node_name: str):\n        \"\"\"Returns a node instance by its name.\"\"\"\n        return next(node for node in self.nodes if node.node_name == node_name)\n\n    def _update_source_info(self, current_node, state):","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/ScrapeGraphAI/Scrapegraph-ai/blob/532dfffbf6ee823a6c9cf8cfedc24a93bf026780/scrapegraphai/graphs/base_graph.py#L94-L130","documentation":"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__.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure the conditional node has exactly two (from_node=conditional, to_node=...) entries in the edges list — one for true, one for false.","Route any extra downstream nodes off the branch targets instead of off the conditional node itself.","If you intended a single successor, use a normal 'node' type instead of 'conditional_node'."],"exampleFix":"# before\ngraph = BaseGraph(nodes=[cond, a], edges=[(cond, a)])  # cond is conditional_node\n\n# after\ngraph = BaseGraph(nodes=[cond, a, b], edges=[(cond, a), (cond, b)])","handlingStrategy":"validation","validationCode":"from collections import Counter\nout_deg = Counter(f.node_name for f, t in edges if getattr(f, 'node_type', '') == 'conditional_node')\nfor name, deg in out_deg.items():\n    assert deg == 2, f'conditional node {name} has {deg} outgoing edges, needs exactly 2'","typeGuard":"def conditional_edges_valid(nodes, edges) -> bool:\n    from collections import Counter\n    cond = {n.node_name for n in nodes if n.node_type == 'conditional_node'}\n    c = Counter(f.node_name for f, _ in edges if f.node_name in cond)\n    return all(c[n] == 2 for n in cond)","tryCatchPattern":"try:\n    g = BaseGraph(nodes=nodes, edges=edges, entry_point=entry)\nexcept ValueError as e:\n    if 'exactly two outgoing edges' in str(e):\n        # fix edges list and retry\n        raise\n    raise","preventionTips":["Validate conditional-node out-degree in a helper before constructing BaseGraph.","Never attach extra edges (logging, cleanup) directly to conditional nodes.","Write a unit test for custom graph topologies."],"tags":["graph-topology","conditional-node","validation","edges"],"backgroundTag":"invalid-graph-topology","analyzedSha":"532dfffbf6ee823a6c9cf8cfedc24a93bf026780","analyzedAt":"2026-08-28T15:19:38.821Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}