alibaba/spring-ai-alibaba · error · IllegalArgumentException
recursionLimit must be > 0!
Error message
recursionLimit must be > 0!
What it means
CompileConfig.Builder.recursionLimit enforces a strictly positive recursion limit because graph execution uses it to cap the number of node transitions and prevent infinite loops. Passing 0 or a negative value throws IllegalArgumentException.
Source
Thrown at spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/CompileConfig.java:182
/**
* Builder class for creating instances of CompileConfig. It allows setting various
* options such as savers, interrupts, and lifecycle listeners in a fluent manner.
*/
public static class Builder {
private final CompileConfig config;
/**
* Initializes the builder with the provided compile configuration.
* @param config The base configuration to start from.
*/
protected Builder(CompileConfig config) {
this.config = new CompileConfig(config);
}
public Builder recursionLimit(int recursionLimit) {
if( recursionLimit <= 0 ) {
throw new IllegalArgumentException("recursionLimit must be > 0!");
}
this.config.recursionLimit = recursionLimit;
return this;
}
/**
* Sets whether the thread should be released during execution.
* @param releaseThread Flag indicating whether to release the thread.
* @see BaseCheckpointSaver#release(RunnableConfig)
* @return This builder instance for method chaining.
*/
public Builder releaseThread(boolean releaseThread) {
this.config.releaseThread = releaseThread;
return this;
}
/**
* Sets the observation registry for monitoring and tracing.View on GitHub (pinned to f82da0b50f)
Solutions
- Pass a positive integer (e.g. 25–50 for typical agent loops).
- Default the config value: int limit = configured > 0 ? configured : 25;
- Prefer CompileConfig.recursionLimit() over the deprecated CompiledGraph.setMaxIterations.
Example fix
// before CompileConfig cfg = CompileConfig.builder().recursionLimit(0).build(); // after CompileConfig cfg = CompileConfig.builder().recursionLimit(25).build();
Defensive patterns
Strategy: validation
Validate before calling
if (configuredLimit <= 0) configuredLimit = 25; CompileConfig cfg = CompileConfig.builder().recursionLimit(configuredLimit).build();
Type guard
Integer safeRecursionLimit(Integer v) { return (v == null || v <= 0) ? 25 : v; } Try / catch
try { cfg = CompileConfig.builder().recursionLimit(n).build(); } catch (IllegalArgumentException e) { cfg = CompileConfig.builder().recursionLimit(25).build(); } Prevention
- Never pass raw config values; clamp/normalize before calling recursionLimit.
- Default unset properties to a positive constant.
- Use CompileConfig.recursionLimit instead of the deprecated setMaxIterations.
When it happens
Trigger: Calling new CompileConfig.Builder().recursionLimit(0) or recursionLimit(negative), often from a config value that defaulted to 0 or was computed as -1.
Common situations: Loading recursion limit from application properties that were unset (0); arithmetic producing a non-positive value; copying a config object whose limit was never initialized.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/51495e1005ad1806.
Report an issue: GitHub.