{"record":{"id":"26768ac80386914d","repo":"apache/druid","slug":"s-s-extractorid-s","errorCode":null,"errorMessage":"%s: %s, extractorID = %s","messagePattern":"(.+?): (.+?), extractorID = (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions-core/lookups-cached-global/src/main/java/org/apache/druid/query/lookup/NamespaceLookupExtractorFactory.java","lineNumber":224,"sourceCode":"  // Grab the latest snapshot from the CacheScheduler's entry\n  @Override\n  public LookupExtractor get()\n  {\n    final Lock readLock = startStopSync.readLock();\n    try {\n      readLock.lockInterruptibly();\n    }\n    catch (InterruptedException e) {\n      throw new RuntimeException(e);\n    }\n    try {\n      if (entry == null) {\n        throw new ISE(\"Factory [%s] not started\", extractorID);\n      }\n      final CacheScheduler.CacheState cacheState = entry.getCacheState();\n      if (cacheState instanceof CacheScheduler.NoCache) {\n        final String noCacheReason = ((CacheScheduler.NoCache) cacheState).name();\n        throw new ISE(\"%s: %s, extractorID = %s\", entry, noCacheReason, extractorID);\n      }\n      CacheScheduler.VersionedCache versionedCache = (CacheScheduler.VersionedCache) cacheState;\n      final byte[] v = StringUtils.toUtf8(versionedCache.getVersion());\n      final byte[] id = StringUtils.toUtf8(extractorID);\n      final byte injectiveByte = isInjective() ? (byte) 1 : (byte) 0;\n      final Supplier<byte[]> cacheKey = () ->\n          ByteBuffer\n              .allocate(CLASS_CACHE_KEY.length + id.length + 1 + v.length + 1 + 1)\n              .put(CLASS_CACHE_KEY)\n              .put(id).put((byte) 0xFF)\n              .put(v).put((byte) 0xFF)\n              .put(injectiveByte)\n              .array();\n      return versionedCache.asLookupExtractor(isInjective(), cacheKey);\n    }\n    finally {\n      readLock.unlock();\n    }","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/lookups-cached-global/src/main/java/org/apache/druid/query/lookup/NamespaceLookupExtractorFactory.java#L206-L242","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Re-announce/restart the lookup so the cache is rescheduled and returns to a VersionedCache state.","Check the noCache reason in the exception/logs (e.g. \"closed\" vs \"failed\") and fix the underlying cause (restore the data file, fix connectivity).","Avoid deleting/overwriting the lookup while queries are running; coordinate lookup updates with query load.","Handle this exception in query paths by retrying after lookup re-initialization."],"exampleFix":"// before: delete then get\nlookupManager.delete(id);\nLookupExtractor l = factory.get(); // ISE: NoCache\n// after: get before teardown, or re-create first\nLookupExtractor l = factory.get();\nlookupManager.delete(id);","handlingStrategy":"retry","validationCode":"// java\n// no pre-call check exposed; verify lookup still announced\nboolean live = lookupManager.get(id) != null;","typeGuard":null,"tryCatchPattern":"// java\ntry { LookupExtractor l = factory.get(); }\ncatch (IllegalStateException e) {\n  // parse noCache reason; re-announce lookup then retry\n  lookupManager.add(id, lookupConfig);\n}","preventionTips":["Coordinate lookup deletes/updates with query traffic.","Monitor CacheScheduler close/failed events.","Keep underlying data files stable during lookups' poll period."],"tags":["lookup","cache-scheduler","concurrency","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"}