quarkusio/quarkus · error · CacheException
An existing cached value type does not match the requested…
Error message
An existing cached value type does not match the requested type
What it means
Thrown by CaffeineCacheImpl when a value already stored in the cache cannot be cast to the generic type V requested by the caller via the Cache API (the cache stores values as Object). This happens when the same cache name is used with different value types, e.g. after changing a method's return type or calling put() with a mismatched type. The ClassCastException is wrapped in a CacheException to give a clearer message.
Solutions
- Use a distinct @CacheName/cache name for each value type
- Clear/invalidate the cache (or restart the app) so stale entries of the old type are removed
- Ensure the cached method's return type and all callers agree on one type
Example fix
// before
@CacheName("myCache")
public String getName(long id) { ... }
public User getUser(long id) { ... } // same cache, different type
// after
@CacheName("nameCache")
public String getName(long id) { ... }
@CacheName("userCache")
public User getUser(long id) { ... } Defensive patterns
Strategy: type-guard
Validate before calling
// store one type per cache name and verify before reads
Object existing = cache.get(key, k -> null);
if (existing != null && !(existing instanceof ExpectedType)) {
cache.invalidate(key).await().indefinitely();
} Type guard
boolean isExpectedType(Object value) {
return value instanceof ExpectedType;
} Try / catch
try {
V value = cache.get(key, loader);
} catch (CacheException e) {
if (e.getCause() instanceof ClassCastException) {
cache.invalidate(key).await().indefinitely();
value = cache.get(key, loader);
} else { throw e; }
} Prevention
- One cache name per value type
- Invalidate stale entries after changing a cached method's return type
- Restart or clear caches after dev-mode hot reloads that change types
When it happens
Trigger: Calling get/getAsync/put on a Caffeine-backed cache whose existing entries were stored under a different value type; the unchecked cast (V) value throws ClassCastException.
Common situations: Reusing a cache name for two methods with different return types; changing a cached method's return type while old entries persist; deserialization/classloader changes across hot redeployment in dev mode.
Related errors
- An existing cached value type does not match the type…
- The access-based expiration policy can only be changed if…
- The maximum size can only be changed if the cache was…
- The write-based expiration policy can only be changed if…
- Unable to instantiate weigher class
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/43e184f07f7780ad.
Report an issue: GitHub.
Appendix: source
Thrown at extensions/cache/runtime/src/main/java/io/quarkus/cache/runtime/caffeine/CaffeineCacheImpl.java:192
public <V> CompletableFuture<V> getIfPresent(Object key) {
Objects.requireNonNull(key, NULL_KEYS_NOT_SUPPORTED_MSG);
CompletableFuture<Object> existingCacheValue = cache.getIfPresent(key);
if (existingCacheValue == null) {
return null;
} else {
LOGGER.tracef("Key [%s] found in cache [%s]", key, cacheInfo.name);
// cast, but still throw the CacheException in case it fails
return unwrapCacheValueOrThrowable(existingCacheValue)
.thenApply(new Function<>() {
@SuppressWarnings("unchecked")
@Override
public V apply(Object value) {
try {
return (V) value;
} catch (ClassCastException e) {
throw new CacheException("An existing cached value type does not match the requested type", e);
}
}
});
}
}
/**
* Returns a {@link CompletableFuture} holding the cache value identified by {@code key}, obtaining that value from
* {@code valueLoader} if necessary. The value computation is done synchronously on the calling thread and the
* {@link CompletableFuture} is immediately completed before being returned.
*
* @param key cache key
* @param valueLoader function used to compute the cache value if {@code key} is not already associated with a value
* @return a {@link CompletableFuture} holding the cache value
* @throws CacheException if an exception is thrown during the cache value computation
*/
private <K, V> CompletableFuture<Object> getFromCaffeine(K key, Function<K, V> valueLoader) {View on GitHub (pinned to e1c734241f)