alibaba/Sentinel · error · IllegalArgumentException
Cache max capacity should be positive: ${size}
Error message
Cache max capacity should be positive: ${size} What it means
ConcurrentLinkedHashMapWrapper is the CacheMap implementation backing Sentinel's hot-parameter flow statistics. Its constructor rejects a non-positive max capacity with IllegalArgumentException, because the underlying ConcurrentLinkedHashMap.Builder().maximumWeightedCapacity(size) requires a weight limit greater than zero. The capacity typically comes from the param flow rule's durationInSec-related cache sizing (e.g. ParameterMetric creation) or user-supplied cache size configuration.
Source
Thrown at sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/statistic/cache/ConcurrentLinkedHashMapWrapper.java:37
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
import com.googlecode.concurrentlinkedhashmap.Weighers;
/**
* A {@link ConcurrentLinkedHashMap} wrapper for the universal {@link CacheMap}.
*
* @author Eric Zhao
* @since 0.2.0
*/
public class ConcurrentLinkedHashMapWrapper<T, R> implements CacheMap<T, R> {
private static final int DEFAULT_CONCURRENCY_LEVEL = 16;
private final ConcurrentLinkedHashMap<T, R> map;
public ConcurrentLinkedHashMapWrapper(long size) {
if (size <= 0) {
throw new IllegalArgumentException("Cache max capacity should be positive: " + size);
}
this.map = new ConcurrentLinkedHashMap.Builder<T, R>()
.concurrencyLevel(DEFAULT_CONCURRENCY_LEVEL)
.maximumWeightedCapacity(size)
.weigher(Weighers.singleton())
.build();
}
public ConcurrentLinkedHashMapWrapper(ConcurrentLinkedHashMap<T, R> map) {
if (map == null) {
throw new IllegalArgumentException("Invalid map instance");
}
this.map = map;
}
@Override
public boolean containsKey(T key) {
return map.containsKey(key);View on GitHub (pinned to a3f40ba8e9)
Solutions
- Pass a positive long as the max capacity, e.g. at least 1 (typical production values are thousands, like CacheMap defaults 4 * 1024)
- Find where the size value originates (rule config or constant) and clamp it to a sane positive minimum before constructing the cache
- If you intended "no eviction", pick a large bounded value instead of 0
Example fix
// before long size = computeCapacity(rule); // may return 0 CacheMap<Object, AtomicLong> cache = new ConcurrentLinkedHashMapWrapper<>(size); // after long size = Math.max(1, computeCapacity(rule)); CacheMap<Object, AtomicLong> cache = new ConcurrentLinkedHashMapWrapper<>(size);
Defensive patterns
Strategy: validation
Validate before calling
long capacity = Math.max(1, configuredCacheCapacity); CacheMap<Object, AtomicLong> cache = new ConcurrentLinkedHashMapWrapper<>(capacity);
Try / catch
try {
return new ConcurrentLinkedHashMapWrapper<>(size);
} catch (IllegalArgumentException e) {
return new ConcurrentLinkedHashMapWrapper<>(DEFAULT_CAPACITY);
} Prevention
- Clamp all size-derived config to a positive minimum before cache construction
- Remember 0 means invalid here, not unlimited
When it happens
Trigger: new ConcurrentLinkedHashMapWrapper<>(size) with size == 0 or negative; in practice, a ParamFlowStatistic/CacheMap creation path where the computed or configured cache capacity is 0 (e.g. misconfigured capacity constant or a rule/config value of 0 fed into cache construction).
Common situations: Setting a cache-capacity-related configuration to 0 intending "unlimited" (0 actually means invalid here); arithmetic that computes capacity from a difference that evaluates to 0 or negative; upgrading Sentinel where the cache wrapper constructor gained this validation.
Related errors
- Invalid map instance
- maxSize must > 0
- keys empty or null: ${keys}
- keys empty or null
- Max entry count should be at least 1:
AI-assisted analysis of alibaba/Sentinel@a3f40ba8e9 (2026-08-14).
Data as JSON: /api/errors/29143a4f9350a137.
Report an issue: GitHub.