alibaba/spring-ai-alibaba · error · IllegalStateException

Failed to add nested convergence node to queue:

Error message

Failed to add nested convergence node to queue: 

What it means

During convergence-node detection, when a nested convergence point's source set changes, the node is re-queued for another fixpoint iteration. If queue.offer fails (only possible for a capacity-bounded deque), an IllegalStateException with this message is thrown. It is a defensive invariant check, not an expected runtime failure.

Solutions

  1. Confirm the dependency artifact is an unmodified official release.
  2. Report the graph structure and node ids to the maintainers if reproducible.
  3. Rebuild/redownload spring-ai-alibaba-graph-core to eliminate artifact corruption.
Defensive patterns

Strategy: retry

Try / catch

try { graph.compile(); } catch (IllegalStateException e) { if (e.getMessage().startsWith("Failed to add nested convergence node")) { /* rebuild dependency / report bug */ } }

Prevention

When it happens

Trigger: queue.offer(nestedConvergence) returns false while re-queueing a nested convergence node whose incoming sources changed during the traversal — practically impossible with an unbounded ArrayDeque.

Common situations: Not reachable in normal use; indicates a corrupted artifact or modified internals.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/internal/ParallelEdgeProcessor.java:329

						.collect(Collectors.toSet());

				if (!parallelTargets.isEmpty()) {
					String nestedConvergence = findConvergenceNode(parallelTargets);
					if (nestedConvergence != null) {
						// Update reachability: all sources that reached current also reach nested convergence
						Set<String> nestedSources = reachableFrom.computeIfAbsent(nestedConvergence, k -> new HashSet<>());
						int sizeBefore = nestedSources.size();
						nestedSources.addAll(sources);
						boolean sourcesChanged = nestedSources.size() > sizeBefore;

						if (nestedSources.size() == startNodeIds.size()) {
							return nestedConvergence;
						}

						// Only queue if sources actually changed (prevents infinite loops in cycles)
						if (sourcesChanged && nestedSources.size() < startNodeIds.size()) {
							if (!queue.offer(nestedConvergence)) {
								throw new IllegalStateException("Failed to add nested convergence node to queue: " + nestedConvergence);
							}
						}
					}
				}
				continue;
			}

			EdgeValue target = edge.target();
			if (target.id() == null) {
				// Conditional edge - skip for now
				continue;
			}

			String nextNode = target.id();

			// Update reachability: all sources that reached current also reach nextNode
			Set<String> nextSources = reachableFrom.computeIfAbsent(nextNode, k -> new HashSet<>());
			int sizeBefore = nextSources.size();

View on GitHub (pinned to f82da0b50f)