alibaba/spring-ai-alibaba · error · GraphStateException

Conditional multi-command mapping from node '

Error message

Conditional multi-command mapping from node '

What it means

During CompiledGraph construction, conditional edges emitting multiple commands (multi-command mappings) are validated: every mapped target node must exist in the graph. If any target id has no node factory, a GraphStateException naming the source node and missing targets is thrown.

Source

Thrown at spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/CompiledGraph.java:175

								e.sourceId(),
								edgeCondition,
								nodeFactories,
								keyStrategyMap,
								compileConfig);

						nodeFactories.put(conditionalParallelNode.id(), conditionalParallelNode.actionFactory());
						edges.put(e.sourceId(), new EdgeValue(conditionalParallelNode.id()));

						// Find parallel node targets from mappings
						var mappedNodeIds = edgeCondition.mappings().values().stream()
								.collect(Collectors.toSet());

						// Validate that all mapped nodes exist in the graph
						var missingNodeIds = mappedNodeIds.stream()
								.filter(nodeId -> !nodeFactories.containsKey(nodeId))
								.collect(Collectors.toSet());
						if (!missingNodeIds.isEmpty()) {
							throw new GraphStateException("Conditional multi-command mapping from node '"
									+ e.sourceId() + "' references unknown target nodes: " + missingNodeIds);
						}

						var parallelNodeTargets = findParallelNodeTargets(mappedNodeIds);
						if (parallelNodeTargets.size() > 1) {
							throw Errors.illegalMultipleTargetsOnParallelNode
									.exception(e.sourceId(), parallelNodeTargets);
						}
						if (parallelNodeTargets.isEmpty()) {
							throw Errors.illegalMultipleTargetsOnParallelNode.exception(e.sourceId(), 0);
						}
						// Set edge from ConditionalParallelNode to the next node.
						// Conditional parallel branches currently require a single converged target.
						edges.put(conditionalParallelNode.id(), new EdgeValue(parallelNodeTargets.iterator().next()));
						// The ConditionalParallelNode will handle parallel execution internally
					} else {
						// Single Command action - same as regular single target edge
						edges.put(e.sourceId(), target);

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Ensure every id returned by the conditional mapping is registered with graph.addNode(id, ...).
  2. Log or print mappedNodeIds and compare against nodeFactories keys.
  3. Fix typos between the routing function's returned names and node ids.

Example fix

// before
.stateGraph("router", StateGraph::END) // mapping returns "anlyzer"
.addNode("analyzer", node)            // typo in node id
// after
.addNode("analyzer", node)            // mapping returns "analyzer" consistently
Defensive patterns

Strategy: validation

Validate before calling

Set<String> mapped = routingMap.values().stream().flatMap(Set::stream).collect(Collectors.toSet()); Set<String> missing = new HashSet<>(mapped); missing.removeAll(registeredNodeIds); if (!missing.isEmpty()) throw new IllegalStateException("Unknown routing targets: " + missing);

Try / catch

try { compiled = graph.compile(config); } catch (GraphStateException e) { log.error("Graph validation failed: {}", e.getMessage()); }

Prevention

When it happens

Trigger: Adding a conditional edge whose edge mapping/lambda returns node ids not registered via addNode — e.g. typos in target names or targets added later/removed during refactoring.

Common situations: Renaming a node but not the routing map strings; conditional routes referencing nodes that only exist in another graph variant; dynamic node registration skipped.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09). Data as JSON: /api/errors/4dd20a2dd00bc44e. Report an issue: GitHub.