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

Builder.maxCachedThreads(int) validates its argument and throws IllegalArgumentException if a negative value is passed. The cache of thread states can be disabled with 0, but any negative count is invalid.

Source

Thrown at spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/mysql/MysqlSaver.java:600

	/**
	 * A builder for MysqlSaver.
	 */
	public static class Builder {
		private DataSource dataSource;
		private CreateOption createOption = CreateOption.CREATE_IF_NOT_EXISTS;
		private StateSerializer stateSerializer;
		private int maxCachedThreads = 1024;

		/**
		 * Sets the maximum number of latest checkpoints retained in memory.
		 *
		 * @param maxCachedThreads max cached threads, or 0 to disable the cache
		 * @return this builder
		 */
		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;
		}

		/**
		 * Sets the state serializer
		 *
		 * @param stateSerializer the state serializer
		 * @return this builder
		 */
		public Builder stateSerializer(StateSerializer stateSerializer) {
			this.stateSerializer = stateSerializer;
			return this;
		}

		/**
		 * Sets the datasource

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Pass a non-negative integer; use 0 to disable the thread cache entirely.
  2. Clamp or validate externally supplied config values before passing them to the builder.
  3. Map a '-1 means unlimited' convention to a large positive number or to 0 explicitly before building.

Example fix

// before
int threads = Integer.parseInt(env.getProperty("cache.threads")); // -1 = unlimited convention
MysqlSaver.builder().maxCachedThreads(threads); // IllegalArgumentException
// after
int threads = Math.max(0, Integer.parseInt(env.getProperty("cache.threads", "0")));
MysqlSaver.builder().maxCachedThreads(threads);
Defensive patterns

Strategy: validation

Validate before calling

int t = config.maxCachedThreads();
if (t < 0) t = 0; // or map your '-1 = unlimited' convention explicitly
builder.maxCachedThreads(t);

Prevention

When it happens

Trigger: Calling MysqlSaver.builder().maxCachedThreads(-1) (or computing the value from a config/property that resolves negative, e.g. an int parsed from a bad environment variable) before build().

Common situations: Feeding maxCachedThreads from external configuration where a sentinel like -1 meant 'unlimited' in the developer's own config convention; arithmetic producing a negative value; typos in config keys shifting values.

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