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
RoutingAgent's retry loop failed to obtain a structurally valid routing decision from the LLM after exhausting maxRetries attempts. The library throws IllegalStateException because routing cannot proceed without a decision; lastInvalidDecision records the final rejected output for debugging. This is a fail-fast guard around non-deterministic LLM structured output.
Source
Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/flow/node/RoutingNode.java:279
rootAgent.name(), attempt, maxRetries, invalidAgents);
}
}
else {
lastInvalidDecision = Collections.emptyList();
logger.warn("RoutingAgent {} attempt {}/{} returned empty agent list",
rootAgent.name(), attempt, maxRetries);
}
}
catch (Exception e) {
if (attempt == maxRetries) {
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);
}
}
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.
* Each agent has a targeted sub-question optimized for that agent's capabilities.
*/
public static class RoutingDecision {
private List<AgentRouting> agents;
public RoutingDecision() {
this.agents = new ArrayList<>();
}
public RoutingDecision(List<AgentRouting> agents) {
this.agents = agents != null ? agents : Collections.emptyList();
}View on GitHub (pinned to f82da0b50f)
Solutions
- Inspect lastInvalidDecision in the exception message and fix the router prompt/schema so valid decisions are produced
- Verify the decision keys returned by the model exactly match the condition keys registered in the routing/conditional mapping
- Use a model with native structured output / JSON mode and increase maxTokens to avoid truncation
- Increase maxRetries or wrap the call with an application-level fallback route (default branch)
- Check provider health/quota if the log line 'encountered an error, will retry' repeats with transport errors
Example fix
// before
RoutingAgent agent = RoutingAgent.builder().model(weakModel).build();
// after
RoutingAgent agent = RoutingAgent.builder()
.model(structuredOutputModel)
.maxRetries(5)
.build(); Defensive patterns
Strategy: retry
Validate before calling
if (decision == null || !validBranchKeys.contains(decision)) throw new IllegalStateException("Router returned invalid decision: " + decision); Type guard
static boolean isValidDecision(String d, Set<String> keys) { return d != null && keys.contains(d); } Try / catch
try { return routingAgent.apply(state); } catch (IllegalStateException e) { log.warn("Routing failed: {}", e.getMessage()); return defaultRoute; } Prevention
- Use a model with native structured output support for the router
- Keep branch keys in one shared constant set used by both prompt and validation
- Set maxTokens high enough to avoid truncated decisions
- Add a deterministic default/fallback branch
When it happens
Trigger: Calling RoutingAgent (via apply -> getDecisionWithRetry) when the underlying model repeatedly returns a routing decision that fails validation (e.g. wrong branch key, malformed structured output, missing required decision fields) on every attempt up to maxRetries.
Common situations: Model not honoring the structured-output schema (weak model or no JSON mode), router prompt listing branch names that don't match the registered conditional agents, response truncated by a low maxTokens setting, or transient provider errors consuming all retries.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- Failed to get valid decision after %d retries. Last invalid
- RoutingAgent failed to get valid decision after retries. In
- Model call failed, maximum number of retries reached:${excep
- Model call failed, maximum number of retries reached.
- Model call failed, maximum number of retries reached. ${maxA
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/735d5983980769a7.
Report an issue: GitHub.