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
- Confirm the dependency artifact is an unmodified official release.
- Report the graph structure and node ids to the maintainers if reproducible.
- 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
- Use official release artifacts only
- Pin dependency versions
- Report reproducible graphs to maintainers
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
- Failed to add next node to queue:
- Failed to add start node to queue:
- CreatePluginError
- no generator found!
- SYSTEM_ERROR
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)