quarkusio/quarkus · error · CacheException

An existing cached value type does not match the type return

Error message

An existing cached value type does not match the type returned by the value loading function

What it means

Thrown by CaffeineCacheImpl.cast when a value produced by the value loading function (or retrieved from the cache) cannot be cast to the generic type T expected by the caller of get(). The cache stores Object values, so mixing value types in one cache triggers a ClassCastException wrapped in a CacheException.

Source

Thrown at extensions/cache/runtime/src/main/java/io/quarkus/cache/runtime/caffeine/CaffeineCacheImpl.java:344

                    "maximum-size configuration value");
        }
    }

    // For testing purposes only.
    public CaffeineCacheInfo getCacheInfo() {
        return cacheInfo;
    }

    public long getSize() {
        return cache.synchronous().estimatedSize();
    }

    @SuppressWarnings("unchecked")
    private <T> T cast(Object value) {
        try {
            return (T) value;
        } catch (ClassCastException e) {
            throw new CacheException(
                    "An existing cached value type does not match the type returned by the value loading function", e);
        }
    }

    @SuppressWarnings("unchecked")
    private <V> Function<V, V> fromCacheValue() {
        return (Function<V, V>) FROM_CACHE_VALUE;
    }

    private interface StatsRecorder {

        void onValueAbsent();

        <K> void doRecord(K key);

    }

    private static class NoopStatsRecorder implements StatsRecorder {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Ensure the loading function's return type matches the cache's declared value type
  2. Use a separate cache name per value type
  3. Clear the cache to drop stale entries of the old type

Example fix

// before
Cache cache = cacheManager.getCache("shared");
String s = cache.get("k", id -> new User(id)); // loader returns User, caller wants String
// after
Cache userCache = cacheManager.getCache("userCache");
User u = userCache.get("k", id -> new User(id));
Defensive patterns

Strategy: type-guard

Validate before calling

// ensure loader output matches the cache's value type
V loaded = loader.apply(key);
if (!(loaded instanceof ExpectedType)) {
    throw new IllegalArgumentException("loader returned wrong type");
}

Type guard

boolean loaderReturnsExpectedType(Function<K, ?> loader, K key) {
    return loader.apply(key) instanceof ExpectedType;
}

Try / catch

try {
    T 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

When it happens

Trigger: Calling get(key, loadingFunction) where the loading function returns a different type than the entries already cached under that key, or where callers use different generic types for the same cache.

Common situations: A loader whose return type was changed; two application methods sharing a cache name but returning different types; dev-mode hot reload retaining old entries.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/0071ba3fa311ab8f. Report an issue: GitHub.