apache/druid · error · IllegalStateException
Expected WeakReference, got: %s
Error message
Expected WeakReference, got: %s
What it means
OnHeapNamespaceExtractionCacheManager stores cache ids as WeakReference objects; disposeCache() requires that invariant. If a CacheHandler arrives whose id is not a WeakReference, the manager cannot remove it from its weak-reference collection and throws this ISE, indicating the handler was not created by this manager.
Source
Thrown at extensions-core/lookups-cached-global/src/main/java/org/apache/druid/server/lookup/namespace/cache/OnHeapNamespaceExtractionCacheManager.java:141
{
if (cache.getCache() instanceof ImmutableLookupMap) {
return ((ImmutableLookupMap) cache.getCache()).asLookupExtractor(isOneToOne, cacheKeySupplier);
} else {
return new MapLookupExtractor(cache.getCache(), isOneToOne) {
@Override
public byte[] getCacheKey()
{
return cacheKeySupplier.get();
}
};
}
}
@Override
void disposeCache(CacheHandler cacheHandler)
{
if (!(cacheHandler.id instanceof WeakReference)) {
throw new ISE("Expected WeakReference, got: %s", cacheHandler.id);
}
caches.remove(cacheHandler.id);
}
@Override
int cacheCount()
{
expungeCollectedCaches();
return caches.size();
}
@Override
void monitor(ServiceEmitter serviceEmitter)
{
long numEntries = 0;
long heapSizeInBytes = 0;
expungeCollectedCaches();
for (WeakReference<Map<String, String>> cacheRef : caches) {View on GitHub (pinned to 9b90983fd2)
Solutions
- Only dispose CacheHandlers obtained from the same CacheScheduler/manager that created them.
- Verify the CacheHandler implementation matches the active namespace extraction cache manager.
- If constructing handlers in tests, use manager/scheduler factory methods so ids are WeakReferences.
Example fix
// before CacheHandler h = new CacheHandler(scheduler, someMap, id); // raw id onHeapManager.disposeCache(h); // ISE // after Entry e = scheduler.schedule(namespace); scheduler.delete(e); // proper lifecycle, correct id type
Defensive patterns
Strategy: type-guard
Validate before calling
if (!(cacheHandler.id instanceof WeakReference)) { throw new IllegalArgumentException("handler not created by on-heap manager"); } Type guard
boolean disposable(CacheHandler h) { return h.id instanceof WeakReference; } Try / catch
try { manager.disposeCache(handler); } catch (IllegalStateException e) { if (e.getMessage().startsWith("Expected WeakReference")) { /* wrong manager; dispose via originating scheduler */ } else { throw e; } } Prevention
- Dispose handlers via the scheduler/manager that created them
- Never construct CacheHandler manually with a raw id
- Keep lookup extension versions consistent across the cluster
When it happens
Trigger: Calling disposeCache(cacheHandler) with a handler whose id is a plain map or foreign id object — typically a handler built for a different cache manager implementation (e.g. off-heap) or manually constructed.
Common situations: Mixing cache managers (on-heap manager disposing an off-heap CacheHandler); manually constructing CacheHandler with a raw id; classpath mixing of old/new versions of the lookup extension.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/c77f9ca8476bfb21.
Report an issue: GitHub.