alibaba/spring-ai-alibaba · warning

RoutingAgent attempt / returned invalid agent name

Error message

RoutingAgent {} attempt {}/{} returned invalid agent name: {}

What it means

RoutingEdgeAction.getDecisionWithRetry logs this warning each time an LLM routing attempt returns a decision that is not a valid sub-agent name, storing it as lastInvalidDecision for the retry feedback loop. If all retries exhaust, the final failure escalates (exception or fallback depending on code path).

Solutions

  1. Make the routing prompt strict: return exactly one name from the enumerated list
  2. Add parsing that strips wrappers like 'Decision:' or JSON fences before validation
  3. Increase maxRetries and verify error feedback is appended to the retry messages
  4. Fall back to a default agent instead of failing when all attempts are invalid

Example fix

// before
String decision = llmResponse.trim(); // 'Decision: researcher' -> invalid
// after
String decision = llmResponse.replaceAll("(?i)^decision:\\s*", "").trim(); // 'researcher' -> valid
Defensive patterns

Strategy: retry

Validate before calling

String d = normalize(rawResponse);
if (!subAgents.stream().map(Agent::name).toList().contains(d)) { /* append corrective feedback and retry */ }

Type guard

static boolean isKnownAgentName(String s, List<Agent> agents) { return s != null && agents.stream().anyMatch(a -> a.name().equals(s)); }

Try / catch

try { String d = getDecisionWithRetry(state); } catch (Exception e) { if (e is last-retry failure) { routeToDefaultAgent(); } else { throw e; } }

Prevention

When it happens

Trigger: decisionValue parses the LLM response but the value is not among the sub-agent names, on any attempt up to maxRetries; the message includes the attempt number, max, and the invalid name.

Common situations: Model returns 'END'/'none'/explanatory text instead of an agent name; agent list changed but prompt/cache stale; model hallucinating names from similar tasks; non-JSON wrapping like 'Decision: researcher'.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/flow/node/RoutingEdgeAction.java:221

				}

				String decisionValue = decision.agent();

				// Check if it's a valid sub-agent name
				boolean isValidAgent = subAgents.stream()
						.anyMatch(agent -> agent.name().equals(decisionValue));

				if (isValidAgent) {
					if (attempt > 0) {
						logger.info("RoutingAgent {} succeeded on retry attempt {}. Routed to sub-agent: {}",
								rootAgent.name(), attempt, decisionValue);
					}
					return decisionValue;
				}
				else {
					// Invalid agent name, store for next retry
					lastInvalidDecision = decisionValue;
					logger.warn("RoutingAgent {} attempt {}/{} returned invalid agent name: {}",
							rootAgent.name(), attempt, maxRetries, decisionValue);
				}
			}
			catch (Exception e) {
				if (attempt == maxRetries) {
					// Last attempt failed, rethrow the exception
					logger.error("RoutingAgent {} failed on final attempt {}/{}", rootAgent.name(), attempt, maxRetries, e);
					throw e;
				}
				logger.warn("RoutingAgent {} attempt {}/{} encountered an error, will retry", rootAgent.name(), attempt, maxRetries, e);
			}
		}

		// All retries exhausted
		throw new IllegalStateException(
				String.format("Failed to get valid decision after %d retries. Last invalid decision: %s",
						maxRetries, lastInvalidDecision));
	}

View on GitHub (pinned to f82da0b50f)