{"record":{"id":"1c775f4711e0419e","repo":"quarkusio/quarkus","slug":"the-write-based-expiration-policy-can-only-be-chan","errorCode":null,"errorMessage":"The write-based expiration policy can only be changed if the cache was constructed with an expire-after-write configuration value","messagePattern":"The write-based expiration policy can only be changed if the cache was constructed with an expire-after-write configuration value","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/cache/runtime/src/main/java/io/quarkus/cache/runtime/caffeine/CaffeineCacheImpl.java","lineNumber":301,"sourceCode":"    @Override\n    public Set<Object> keySet() {\n        return Set.copyOf(cache.asMap().keySet());\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public <V> void put(Object key, CompletableFuture<V> valueFuture) {\n        cache.put(key, (CompletableFuture<Object>) valueFuture);\n    }\n\n    @Override\n    public void setExpireAfterWrite(Duration duration) {\n        Optional<FixedExpiration<Object, Object>> fixedExpiration = cache.synchronous().policy().expireAfterWrite();\n        if (fixedExpiration.isPresent()) {\n            fixedExpiration.get().setExpiresAfter(duration);\n            cacheInfo.expireAfterWrite = duration;\n        } else {\n            throw new IllegalStateException(\"The write-based expiration policy can only be changed if the cache was \" +\n                    \"constructed with an expire-after-write configuration value\");\n        }\n    }\n\n    @Override\n    public void setExpireAfterAccess(Duration duration) {\n        Optional<FixedExpiration<Object, Object>> fixedExpiration = cache.synchronous().policy().expireAfterAccess();\n        if (fixedExpiration.isPresent()) {\n            fixedExpiration.get().setExpiresAfter(duration);\n            cacheInfo.expireAfterAccess = duration;\n        } else {\n            throw new IllegalStateException(\"The access-based expiration policy can only be changed if the cache was \" +\n                    \"constructed with an expire-after-access configuration value\");\n        }\n    }\n\n    @Override\n    public void setMaximumSize(long maximumSize) {","sourceCodeStart":283,"sourceCodeEnd":319,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/cache/runtime/src/main/java/io/quarkus/cache/runtime/caffeine/CaffeineCacheImpl.java#L283-L319","documentation":"CaffeineCacheImpl.setExpireAfterWrite only works when the cache was created with an expire-after-write value; Caffeine exposes the write-based FixedExpiration policy only if so configured. If the policy is absent, changing it is meaningless, so an IllegalStateException is thrown.","triggerScenarios":"Calling setExpireAfterWrite (e.g. from testConfig during tests) on a cache whose Quarkus config lacks quarkus.cache.caffeine.<name>.expire-after-write.","commonSituations":"Tests that programmatically tune expiration without declaring the TTL in application.properties; caches configured only with maximum-size or expire-after-access.","solutions":["Add expire-after-write to the cache config (quarkus.cache.caffeine.<name>.expire-after-write)","Only call setExpireAfterWrite for caches known to be write-expiring (check getCacheInfo)","Rebuild/recreate the cache with the desired policy if runtime changes are required"],"exampleFix":"// before (application.properties has no expire-after-write)\ncache.setExpireAfterWrite(Duration.ofSeconds(30));\n// after\n# application.properties\nquarkus.cache.caffeine.myCache.expire-after-write=30S","handlingStrategy":"validation","validationCode":"if (cache.getCacheInfo().expireAfterWrite == null) {\n    throw new IllegalStateException(\"configure expire-after-write before calling setExpireAfterWrite\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    cache.setExpireAfterWrite(duration);\n} catch (IllegalStateException e) {\n    log.warn(\"cache lacks write expiration policy; update application.properties\", e);\n}","preventionTips":["Declare expire-after-write in config for every cache whose TTL you tune at runtime","Check CacheInfo before mutating policies"],"tags":["cache","caffeine","configuration","expiration"],"backgroundTag":"cache-policy-not-configured","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}