{"record":{"id":"d4986f43a57684a8","repo":"apache/druid","slug":"cache-s-is-already-attached","errorCode":null,"errorMessage":"cache [%s] is already attached","messagePattern":"cache \\[(.+?)\\] is already attached","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions-core/lookups-cached-global/src/main/java/org/apache/druid/server/lookup/namespace/cache/OnHeapNamespaceExtractionCacheManager.java","lineNumber":107,"sourceCode":"    expungeCollectedCaches();\n    caches.add(cacheRef);\n    return new CacheHandler(this, cache, cacheRef);\n  }\n\n  @Override\n  public CacheHandler allocateCache()\n  {\n    // Object2ObjectOpenHashMap has a bit smaller footprint than HashMap\n    Map<String, String> cache = new Object2ObjectOpenHashMap<>();\n    // untracked, but disposing will explode if we don't create a weak reference here\n    return new CacheHandler(this, cache, new WeakReference<>(cache));\n  }\n\n  @Override\n  public CacheHandler attachCache(CacheHandler cache)\n  {\n    if (caches.contains((WeakReference<Map<String, String>>) cache.id)) {\n      throw new ISE(\"cache [%s] is already attached\", cache.id);\n    }\n    // replace Object2ObjectOpenHashMap with ImmutableLookupMap\n    final ImmutableLookupMap immutable = ImmutableLookupMap.fromMap(cache.getCache());\n    WeakReference<Map<String, String>> cacheRef = new WeakReference<>(immutable);\n    expungeCollectedCaches();\n    caches.add(cacheRef);\n    return new CacheHandler(this, immutable, cacheRef);\n  }\n\n  @Override\n  public LookupExtractor asLookupExtractor(\n      final CacheHandler cache,\n      final boolean isOneToOne,\n      final Supplier<byte[]> cacheKeySupplier\n  )\n  {\n    if (cache.getCache() instanceof ImmutableLookupMap) {\n      return ((ImmutableLookupMap) cache.getCache()).asLookupExtractor(isOneToOne, cacheKeySupplier);","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/lookups-cached-global/src/main/java/org/apache/druid/server/lookup/namespace/cache/OnHeapNamespaceExtractionCacheManager.java#L89-L125","documentation":"OnHeapNamespaceExtractionCacheManager tracks materialized caches as WeakReferences in a caches collection. attachCache() refuses to attach a CacheHandler whose id is already tracked, throwing this ISE to prevent the same cache being registered twice, which would break disposal accounting and leak tracking.","triggerScenarios":"Calling attachCache(cache) with a CacheHandler already attached (double scheduling/attachment of the same namespace entry, or re-entrant cache creation for the same id).","commonSituations":"Race between two cache-update paths for the same namespace; calling attachCache manually in tests on a handler already managed by the scheduler; reusing a CacheHandler after a failed detach.","solutions":["Attach each CacheHandler exactly once; let the CacheScheduler manage attachment.","Check/track attachment state before calling attachCache, or remove the stale reference first.","Serialize cache creation for a namespace to avoid double-attach races."],"exampleFix":"// before\nmanager.attachCache(cache);\nmanager.attachCache(cache); // ISE: already attached\n// after\nif (!isAttached(cache)) {\n  manager.attachCache(cache);\n}","handlingStrategy":"try-catch","validationCode":"// attach only once per namespace entry\nSet<Object> attached = new HashSet<>();\nif (!attached.add(cache.id)) { /* skip duplicate attach */ }","typeGuard":null,"tryCatchPattern":"try { manager.attachCache(cache); } catch (IllegalStateException e) { if (e.getMessage().contains(\"is already attached\")) { /* ignore: already managed */ } else { throw e; } }","preventionTips":["Let CacheScheduler own attach/detach; avoid manual attachCache","Serialize cache creation per namespace to avoid races"],"tags":["lookup-cache","duplicate","lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}