{"record":{"id":"f834b746e7a37adc","repo":"alibaba/spring-ai-alibaba","slug":"subgraph-not-support-routes-to-parallel-branches-y","errorCode":null,"errorMessage":"subgraph not support routes to parallel branches yet!","messagePattern":"subgraph not support routes to parallel branches yet!","errorType":"exception","errorClass":"GraphStateException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/ProcessedNodesEdgesAndConfig.java","lineNumber":132,"sourceCode":"\n\t\t\tfor (var edgeWithSubgraphTargetId : edgesWithSubgraphTargetId) {\n\n\t\t\t\tvar newEdge = edgeWithSubgraphTargetId.withSourceAndTargetIdsUpdated(subgraphNode, Function.identity(),\n\t\t\t\t\t\tid -> new EdgeValue((Objects.equals(id, subgraphNode.id())\n\t\t\t\t\t\t\t\t? subgraphNode.formatId(sgEdgeStartTarget.id())\n\t\t\t\t\t\t\t\t: id)));\n\t\t\t\tedges.elements.remove(edgeWithSubgraphTargetId);\n\t\t\t\tedges.elements.add(newEdge);\n\t\t\t}\n\t\t\t//\n\t\t\t// Process END Nodes\n\t\t\t//\n\t\t\tvar sgEdgesEnd = processedSubGraphEdges.edgesByTargetId(END);\n\n\t\t\tvar edgeWithSubgraphSourceId = edges.edgeBySourceId(subgraphNode.id()).orElseThrow();\n\n\t\t\tif (edgeWithSubgraphSourceId.isParallel()) {\n\t\t\t\tthrow new GraphStateException(\"subgraph not support routes to parallel branches yet!\");\n\t\t\t}\n\n\t\t\t// Process Interruption (After) Subgraph(s)\n\t\t\tif (interruptsAfter.contains(subgraphNode.id())) {\n\n\t\t\t\tvar exceptionMessage = (edgeWithSubgraphSourceId.target()\n\t\t\t\t\t\t.id() == null) ? \"'interruption after' on subgraph is not supported yet!\"\n\t\t\t\t\t\t\t\t: format(\n\t\t\t\t\t\t\t\t\t\t\"'interruption after' on subgraph is not supported yet! consider to use 'interruption before' node: '%s'\",\n\t\t\t\t\t\t\t\t\t\tedgeWithSubgraphSourceId.target().id());\n\t\t\t\tthrow new GraphStateException(exceptionMessage);\n\t\t\t}\n\n\t\t\tsgEdgesEnd.stream()\n\t\t\t\t\t.map(e -> e.withSourceAndTargetIdsUpdated(subgraphNode, subgraphNode::formatId,\n\t\t\t\t\t\t\tid -> (Objects.equals(id, END) ? edgeWithSubgraphSourceId.target()\n\t\t\t\t\t\t\t\t\t: new EdgeValue(subgraphNode.formatId(id)))))\n\t\t\t\t\t.forEach(edges.elements::add);","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/ProcessedNodesEdgesAndConfig.java#L114-L150","documentation":"After processing a subgraph's END edges, the library needs to route the subgraph node's outgoing edge in the parent graph. Parallel (branching) outgoing edges from a subgraph node are not supported, so process() throws this GraphStateException.","triggerScenarios":"Parent graph defines a parallel branch originating from a subgraph node, e.g. addEdges(\"sub\", List.of(\"a\",\"b\")) or an edge with multiple targets whose source is the subgraph node, then compiling the parent.","commonSituations":"Fan-out patterns where developers want one subgraph result to feed several parallel nodes; usually fixed by inserting an intermediate router/regular node between the subgraph and the branches.","solutions":["Insert an intermediate regular node after the subgraph and make that node the source of the parallel branches","Use a conditional edge with a router action after the subgraph instead of a parallel edge","Restructure so parallelism happens inside the subgraph, not immediately after it","Check the framework version/release notes for updated subgraph parallel support"],"exampleFix":"// before\nouter.addEdge(\"sub\", List.of(\"a\", \"b\"));\n// after\nouter.addNode(\"fanout\", state -> Map.of());\nouter.addEdge(\"sub\", \"fanout\");\nouter.addEdge(\"fanout\", List.of(\"a\", \"b\"));","handlingStrategy":"validation","validationCode":"var e = parent.edges.edgeBySourceId(\"sub\").orElseThrow();\nif (e.isParallel()) throw new IllegalStateException(\"insert an intermediate node before fanning out from a subgraph\");","typeGuard":null,"tryCatchPattern":"try { outer.compile(saver); } catch (GraphStateException ex) { if (ex.getMessage().contains(\"routes to parallel branches\")) { /* restructure with intermediate node */ } else throw ex; }","preventionTips":["Never make a subgraph node the direct source of a parallel branch","Use a router/conditional edge after subgraphs","Check framework docs for subgraph limitations when designing fan-out topologies"],"tags":["graph","subgraph","parallel","unsupported"],"backgroundTag":"unsupported-operation","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}