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

  1. Pass a positive long as the max capacity, e.g. at least 1 (typical production values are thousands, like CacheMap defaults 4 * 1024)
  2. Find where the size value originates (rule config or constant) and clamp it to a sane positive minimum before constructing the cache
  3. 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

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


AI-assisted analysis of alibaba/Sentinel@a3f40ba8e9 (2026-08-14). Data as JSON: /api/errors/29143a4f9350a137. Report an issue: GitHub.