apache/druid · error · IllegalStateException

%s: %s, extractorID = %s

Error message

%s: %s, extractorID = %s

What it means

NamespaceLookupExtractorFactory.get() checks the CacheState of the scheduled cache entry. If the state is CacheScheduler.NoCache, the cache has been explicitly closed/evicted or failed with a recorded reason; get() throws this ISE embedding the entry, the noCache reason, and the extractor ID. It means the lookup existed but its backing cache is no longer usable.

Source

Thrown at extensions-core/lookups-cached-global/src/main/java/org/apache/druid/query/lookup/NamespaceLookupExtractorFactory.java:224

  // Grab the latest snapshot from the CacheScheduler's entry
  @Override
  public LookupExtractor get()
  {
    final Lock readLock = startStopSync.readLock();
    try {
      readLock.lockInterruptibly();
    }
    catch (InterruptedException e) {
      throw new RuntimeException(e);
    }
    try {
      if (entry == null) {
        throw new ISE("Factory [%s] not started", extractorID);
      }
      final CacheScheduler.CacheState cacheState = entry.getCacheState();
      if (cacheState instanceof CacheScheduler.NoCache) {
        final String noCacheReason = ((CacheScheduler.NoCache) cacheState).name();
        throw new ISE("%s: %s, extractorID = %s", entry, noCacheReason, extractorID);
      }
      CacheScheduler.VersionedCache versionedCache = (CacheScheduler.VersionedCache) cacheState;
      final byte[] v = StringUtils.toUtf8(versionedCache.getVersion());
      final byte[] id = StringUtils.toUtf8(extractorID);
      final byte injectiveByte = isInjective() ? (byte) 1 : (byte) 0;
      final Supplier<byte[]> cacheKey = () ->
          ByteBuffer
              .allocate(CLASS_CACHE_KEY.length + id.length + 1 + v.length + 1 + 1)
              .put(CLASS_CACHE_KEY)
              .put(id).put((byte) 0xFF)
              .put(v).put((byte) 0xFF)
              .put(injectiveByte)
              .array();
      return versionedCache.asLookupExtractor(isInjective(), cacheKey);
    }
    finally {
      readLock.unlock();
    }

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Re-announce/restart the lookup so the cache is rescheduled and returns to a VersionedCache state.
  2. Check the noCache reason in the exception/logs (e.g. "closed" vs "failed") and fix the underlying cause (restore the data file, fix connectivity).
  3. Avoid deleting/overwriting the lookup while queries are running; coordinate lookup updates with query load.
  4. Handle this exception in query paths by retrying after lookup re-initialization.

Example fix

// before: delete then get
lookupManager.delete(id);
LookupExtractor l = factory.get(); // ISE: NoCache
// after: get before teardown, or re-create first
LookupExtractor l = factory.get();
lookupManager.delete(id);
Defensive patterns

Strategy: retry

Validate before calling

// java
// no pre-call check exposed; verify lookup still announced
boolean live = lookupManager.get(id) != null;

Try / catch

// java
try { LookupExtractor l = factory.get(); }
catch (IllegalStateException e) {
  // parse noCache reason; re-announce lookup then retry
  lookupManager.add(id, lookupConfig);
}

Prevention

When it happens

Trigger: Calling get()/extractor() after CacheScheduler closed the entry (e.g. delete() called, cached file deleted, or cache closed due to an error), with NoCache states like "closed" or "failed"; racy get during lookup deletion (see testSimpleStartRacyGetDuringDelete).

Common situations: Lookup being updated/replaced concurrently while a query reads it; underlying remote file removed so cache refresh fails and the cache transitions to NoCache; shutdown of the lookup coordinator while queries are in flight.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/26768ac80386914d. Report an issue: GitHub.