quarkusio/quarkus · error · IllegalStateException
The access-based expiration policy can only be changed if th
Error message
The access-based expiration policy can only be changed if the cache was constructed with an expire-after-access configuration value
What it means
CaffeineCacheImpl.setExpireAfterAccess requires that the cache was constructed with an expire-after-access configuration value, since Caffeine only exposes the access-based FixedExpiration policy in that case. Otherwise an IllegalStateException is thrown.
Source
Thrown at extensions/cache/runtime/src/main/java/io/quarkus/cache/runtime/caffeine/CaffeineCacheImpl.java:313
public void setExpireAfterWrite(Duration duration) {
Optional<FixedExpiration<Object, Object>> fixedExpiration = cache.synchronous().policy().expireAfterWrite();
if (fixedExpiration.isPresent()) {
fixedExpiration.get().setExpiresAfter(duration);
cacheInfo.expireAfterWrite = duration;
} else {
throw new IllegalStateException("The write-based expiration policy can only be changed if the cache was " +
"constructed with an expire-after-write configuration value");
}
}
@Override
public void setExpireAfterAccess(Duration duration) {
Optional<FixedExpiration<Object, Object>> fixedExpiration = cache.synchronous().policy().expireAfterAccess();
if (fixedExpiration.isPresent()) {
fixedExpiration.get().setExpiresAfter(duration);
cacheInfo.expireAfterAccess = duration;
} else {
throw new IllegalStateException("The access-based expiration policy can only be changed if the cache was " +
"constructed with an expire-after-access configuration value");
}
}
@Override
public void setMaximumSize(long maximumSize) {
Optional<Policy.Eviction<Object, Object>> eviction = cache.synchronous().policy().eviction();
if (eviction.isPresent()) {
eviction.get().setMaximum(maximumSize);
cacheInfo.maximumSize = maximumSize;
} else {
throw new IllegalStateException("The maximum size can only be changed if the cache was constructed with a " +
"maximum-size configuration value");
}
}
// For testing purposes only.
public CaffeineCacheInfo getCacheInfo() {View on GitHub (pinned to e1c734241f)
Solutions
- Set quarkus.cache.caffeine.<name>.expire-after-access in configuration
- Guard the call by checking the policy is present before mutating
- Recreate the cache with the desired configuration
Example fix
// before # no expire-after-access configured cache.setExpireAfterAccess(Duration.ofMinutes(5)); // after # application.properties quarkus.cache.caffeine.myCache.expire-after-access=5M
Defensive patterns
Strategy: validation
Validate before calling
if (cache.getCacheInfo().expireAfterAccess == null) {
throw new IllegalStateException("configure expire-after-access before calling setExpireAfterAccess");
} Try / catch
try {
cache.setExpireAfterAccess(duration);
} catch (IllegalStateException e) {
log.warn("cache lacks access expiration policy; update application.properties", e);
} Prevention
- Declare expire-after-access in config for caches tuned at runtime
- Keep a checklist of which caches use which policies
When it happens
Trigger: Calling setExpireAfterAccess (e.g. from testConfig) on a cache configured without quarkus.cache.caffeine.<name>.expire-after-access.
Common situations: Attempting to enable access-based expiry at runtime on a cache configured with only expire-after-write or maximum-size.
Related errors
- The write-based expiration policy can only be changed if the
- The maximum size can only be changed if the cache was constr
- Unknown cache type:
- An existing cached value type does not match the requested t
- An existing cached value type does not match the type return
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/36b4dd33db46776d.
Report an issue: GitHub.