alibaba/spring-ai-alibaba · error · IllegalArgumentException

maxCachedThreads must be greater than or equal to 0

Error message

maxCachedThreads must be greater than or equal to 0

What it means

The H2Saver.Builder.maxCachedThreads method validates its argument eagerly and throws IllegalArgumentException if a negative value is passed. maxCachedThreads bounds the number of thread sessions the saver keeps cached, so a negative bound is meaningless and rejected at build time.

Source

Thrown at spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/h2/H2Saver.java:558

		public Builder user(String user) {
			this.user = user;
			return this;
		}

		public Builder password(String password) {
			this.password = password;
			return this;
		}

		public Builder createOption(CreateOption createOption) {
			this.createOption = requireNonNull(createOption, "createOption cannot be null");
			return this;
		}

		public Builder maxCachedThreads(int maxCachedThreads) {
			if (maxCachedThreads < 0) {
				throw new IllegalArgumentException("maxCachedThreads must be greater than or equal to 0");
			}
			this.maxCachedThreads = maxCachedThreads;
			return this;
		}

		private String requireNotBlank(String value, String name) {
			if (requireNonNull(value, format("'%s' cannot be null", name)).isBlank()) {
				throw new IllegalArgumentException(format("'%s' cannot be blank", name));
			}
			return value;
		}

		public H2Saver build() {
			if (stateSerializer == null) {
				this.stateSerializer = StateGraph.DEFAULT_JACKSON_SERIALIZER;
			}
			if (dataSource == null) {
				dataSource = new DriverManagerDataSource(requireNotBlank(jdbcUrl, "jdbcUrl"), user, password);

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Pass a non-negative value; use 0 to disable thread caching rather than a negative number.
  2. Clamp or sanitize external config before calling the builder: Math.max(0, configured).
  3. If 'unlimited' was intended, omit the call and use the builder's default.

Example fix

// before: -1 meaning 'unlimited' from config
builder.maxCachedThreads(config.maxCachedThreads()); // throws
// after: clamp to valid range
builder.maxCachedThreads(Math.max(0, config.maxCachedThreads()));
Defensive patterns

Strategy: validation

Validate before calling

if (configuredMaxCachedThreads < 0) throw new IllegalArgumentException("saver.max-cached-threads must be >= 0 (0 disables caching)");

Type guard

int safeThreads(Integer v) { return v == null ? DEFAULT : Math.max(0, v); }

Try / catch

try { builder.maxCachedThreads(n); }
catch (IllegalArgumentException e) { builder.maxCachedThreads(Math.max(0, n)); }

Prevention

When it happens

Trigger: Calling builder.maxCachedThreads(n) with any n < 0, typically n coming from a computed value, a config property defaulting to -1 for 'unlimited', or a sign error.

Common situations: Mapping a config key like 'saver.max-cached-threads=-1' intending 'unlimited'; parsing user input without clamping; arithmetic producing a negative value.

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/4886602a5acdca8c. Report an issue: GitHub.