alibaba/spring-ai-alibaba · warning

RoutingAgent {} retry attempt {}/{}. Previous invalid decisi

Error message

RoutingAgent {} retry attempt {}/{}. Previous invalid decision: {}

What it means

RoutingEdgeAction.getDecisionWithRetry asks the LLM to pick a sub-agent name; when a decision is invalid, it retries up to maxRetries, injecting error feedback into the prompt. This warning logs each retry attempt, showing the routing agent name, attempt count, and the previous invalid decision.

Source

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

		String lastInvalidDecision = null;

		for (int attempt = 0; attempt <= maxRetries; attempt++) {
			try {
				RoutingDecision decision;

				if (attempt == 0) {
					// First attempt: use original messages
					decision = this.chatClient.prompt().messages(messages).call().entity(this.outputConverter);
				}
				else {
					// Retry attempts: add error feedback to help the model correct its decision
					String errorFeedback = String.format(
							"Previous attempt returned an invalid agent name '%s'. " +
									"Please choose from the available agents: %s.",
							lastInvalidDecision,
							String.join(", ", subAgents.stream().map(Agent::name).toList()));

					logger.warn("RoutingAgent {} retry attempt {}/{}. Previous invalid decision: {}",
							rootAgent.name(), attempt, maxRetries, lastInvalidDecision);

					// Create a new message list with error feedback
					// Try to append to existing SystemMessage, otherwise use UserMessage
					java.util.ArrayList<Message> messagesWithFeedback = new java.util.ArrayList<>();
					boolean systemMessageFound = false;

					for (Message msg : messages) {
						if (msg instanceof SystemMessage && !systemMessageFound) {
							// Append error feedback to the first SystemMessage found
							String enhancedContent = msg.getText() + "\n\n" + errorFeedback;
							messagesWithFeedback.add(new SystemMessage(enhancedContent));
							systemMessageFound = true;
						}
						else {
							messagesWithFeedback.add(msg);
						}
					}

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Rename sub-agents to simple, unambiguous lowercase identifiers
  2. Strengthen the routing prompt to enumerate exact valid agent names and demand one verbatim
  3. Lower temperature for routing calls
  4. Add fuzzy matching of the decision against sub-agent names before declaring it invalid

Example fix

// before
agent named 'Research-Team-Handler v2' // model returns 'research team'
// after
agent named 'research_team' // prompt lists: choose one of: research_team, writer_team
Defensive patterns

Strategy: retry

Validate before calling

List<String> valid = subAgents.stream().map(Agent::name).toList();
if (!valid.contains(decision)) { log.warn("Routing decision '{}' not in {}", decision, valid); }

Type guard

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

Try / catch

try { String d = routingAction.decisionValue(state); } catch (Exception e) { /* all retries exhausted: route to default agent or END */ }

Prevention

When it happens

Trigger: decisionValue (via getDecisionWithRetry) receives from the LLM a string that is not one of subAgents' names; attempt < maxRetries, so the code formats error feedback listing valid agents and retries.

Common situations: Model outputs prose or a paraphrased agent name ('research assistant' vs 'researcher'); sub-agent names contain characters the model mangles; prompt lacks few-shot examples of valid names; LLM temperature too high.

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/6f9e22af52418213. Report an issue: GitHub.