alibaba/spring-ai-alibaba · error · IllegalStateException
Failed to get valid decision after %d retries. Last invalid
Error message
Failed to get valid decision after %d retries. Last invalid decision: %s
What it means
RoutingEdgeAction.getDecisionWithRetry() exhausts all retry attempts without obtaining a structurally valid routing decision from the LLM and throws an IllegalStateException naming the retry count and last invalid decision. The router expected a parseable decision (e.g. structured routing output naming a sub-agent) and the model kept returning invalid or unparseable responses.
Source
Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/flow/node/RoutingEdgeAction.java:236
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));
}
/**
* Response record for structured routing decision output
*/
public record RoutingDecision(String agent) { }
}
View on GitHub (pinned to f82da0b50f)
Solutions
- Use a model that reliably follows the structured routing format (or enable structured output) for the router
- Check the lastInvalidDecision in the message and fix the routing prompt/schema so its output parses
- Verify the agent names the router can return match the registered sub-agents
- Increase maxRetries or configure a fallback decision if supported
Example fix
// before
RoutingAgent.builder().model(weakModel).subAgents(a, b).build();
// after
RoutingAgent.builder().model(structuredOutputModel)
.subAgents(a, b)
.fallbackAgent(defaultAgent) // or validate prompt format
.build(); Defensive patterns
Strategy: retry
Validate before calling
// pre-validate: ensure router model supports structured output and sub-agent names are registered Set<String> valid = subAgents.stream().map(Agent::name).collect(java.util.stream.Collectors.toSet());
Type guard
boolean isParsableDecision(String raw, Set<String> validAgents) { return raw != null && validAgents.contains(raw.trim()); } Try / catch
try { decision = routingEdgeAction.decisionValue(state); } catch (IllegalStateException e) { if (e.getMessage().contains("Failed to get valid decision")) { /* use default route or abort gracefully */ } else throw e; } Prevention
- Use a structured-output-capable model for routing
- Keep routing prompts explicit about the allowed decisions
- Monitor lastInvalidDecision in logs to tune prompts
- Configure a fallback route
When it happens
Trigger: The routing LLM repeatedly returns responses that fail decision parsing/validation for maxRetries attempts while RoutingAgent evaluates its edge action.
Common situations: Model output doesn't match the expected routing format (missing JSON, wrong agent names); weak/small model used for routing; prompt drift after changing sub-agent names; transient model errors consuming all retries.
Related errors
- RoutingAgent failed to get valid decision after retries. In
- Failed to get valid decision after %d retries. Last invalid
- INVALID_PARAMS
- WORKFLOW_CONFIG_INVALID
- No default output or error next node provided
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/8a65799305baad85.
Report an issue: GitHub.