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

  1. Inspect lastInvalidDecision in the exception message and fix the router prompt/schema so valid decisions are produced
  2. Verify the decision keys returned by the model exactly match the condition keys registered in the routing/conditional mapping
  3. Use a model with native structured output / JSON mode and increase maxTokens to avoid truncation
  4. Increase maxRetries or wrap the call with an application-level fallback route (default branch)
  5. 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

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


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