hibernate/hibernate-orm · error · IllegalArgumentException
Maximum capacity has to be at least twice the concurrencyLev
Error message
Maximum capacity has to be at least twice the concurrencyLevel
What it means
BoundedConcurrentHashMap is Hibernate's LIRS-backed bounded map (used for the query plan cache). Its segments need at least two slots each, so the constructor first clamps concurrencyLevel to capacity/2 (min 1) and then rejects the pair when capacity < concurrencyLevel << 1 (except the special case capacity == 1). This IllegalArgumentException means the requested capacity cannot host the requested segment count.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/internal/util/collections/BoundedConcurrentHashMap.java:1461
* internal sizing to try to accommodate this many threads.
* @param evictionStrategy the algorithm used to evict elements from this map
*
* @throws IllegalArgumentException if the initial capacity is negative or the load factor or concurrencyLevel are
* nonpositive.
*/
public BoundedConcurrentHashMap(
int capacity, int concurrencyLevel,
Eviction evictionStrategy) {
if ( capacity < 0 || concurrencyLevel <= 0 ) {
throw new IllegalArgumentException();
}
concurrencyLevel = Math.min( capacity / 2, concurrencyLevel ); // concurrencyLevel cannot be > capacity/2
concurrencyLevel = Math.max( concurrencyLevel, 1 ); // concurrencyLevel cannot be less than 1
// minimum two elements per segment
if ( capacity < concurrencyLevel << 1 && capacity != 1 ) {
throw new IllegalArgumentException( "Maximum capacity has to be at least twice the concurrencyLevel" );
}
if ( evictionStrategy == null ) {
throw new IllegalArgumentException();
}
if ( concurrencyLevel > MAX_SEGMENTS ) {
concurrencyLevel = MAX_SEGMENTS;
}
// Find power-of-two sizes best matching arguments
int sshift = 0;
int ssize = 1;
while ( ssize < concurrencyLevel ) {
++sshift;
ssize <<= 1;
}
segmentShift = 32 - sshift;View on GitHub (pinned to fad1729dce)
Solutions
- Raise capacity to at least 2 * concurrencyLevel (power-of-two capacity is ideal)
- Or lower concurrencyLevel — for small maps 1 or 2 segments are plenty
- Check the cache settings that feed these numbers (e.g. plan cache sizing) and recompute them together, not independently
Example fix
// before: 8 slots cannot host 16 segments Map<K, V> cache = new BoundedConcurrentHashMap<>( 8, 16, Eviction.LIRS ); // after: capacity at least twice the concurrency level Map<K, V> cache = new BoundedConcurrentHashMap<>( 32, 16, Eviction.LIRS );
Defensive patterns
Strategy: validation
Validate before calling
// Validate before constructing a bounded concurrent map
static <K, V> BoundedConcurrentHashMap<K, V> boundedMap(int capacity, int concurrencyLevel, Eviction eviction) {
if ( capacity < 0 ) throw new IllegalArgumentException("capacity must be >= 0");
concurrencyLevel = Math.min( Math.max( Math.min( capacity / 2, concurrencyLevel ), 1 ), capacity == 1 ? 1 : capacity / 2 );
if ( capacity != 1 && capacity < concurrencyLevel << 1 ) {
concurrencyLevel = Math.max( 1, capacity / 2 ); // clamp instead of throwing
}
return new BoundedConcurrentHashMap<>( capacity, concurrencyLevel, eviction );
} Prevention
- Choose capacity as a power of two at least 2x the concurrency level (default 16 segments -> capacity >= 32)
- Derive both values from one sizing knob instead of independent config keys
- When shrinking caches for tests, shrink concurrency first, capacity second
When it happens
Trigger: new BoundedConcurrentHashMap<>(capacity, concurrencyLevel, evictionStrategy) with capacity smaller than twice concurrencyLevel, e.g. (8, 16), (3, 2) — note 3 < 2*2 and 3 != 1, so it throws; (2, 1) passes after clamping.
Common situations: Shrinking Hibernate caches (query plan cache sizing derived from hibernate.query.plan_cache_max_size) or other tuned caches to very small capacities while keeping a default concurrency level of 16; porting constructor arguments from ConcurrentHashMap, which allows any combination.
Related errors
- The {storageEngine} storage engine is not supported
- Unknown Cache Mode: " + setting
- cannot recreate collection while filter is enabled: " + coll
- Audit graph mutation plan used with non-graph action queue
- Audit graph mutation plan used with non-graph action queue
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/1424661359d66b0c.
Report an issue: GitHub.