{"record":{"id":"457e038aa397c80c","repo":"apache/druid","slug":"factory-s-not-started","errorCode":null,"errorMessage":"Factory [%s] not started","messagePattern":"Factory \\[(.+?)\\] not started","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":219,"sourceCode":"  public boolean isInjective()\n  {\n    return injective;\n  }\n\n  // 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();","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/lookups-cached-global/src/main/java/org/apache/druid/query/lookup/NamespaceLookupExtractorFactory.java#L201-L237","documentation":"NamespaceLookupExtractorFactory.get() resolves the CacheScheduler entry for the extractor ID; if the entry is null the factory was never successfully started (start() not called, still awaiting initialization, or it failed/closed). It throws this ISE rather than returning a lookup backed by no cache, per LookupExtractorFactory contract that get() requires a started factory.","triggerScenarios":"Calling get() (directly or via extractor()) before start() completes; racing start() against a close/delete; factory failed during background cache loading so entry never got set.","commonSituations":"Lookup announced to the cluster while its underlying data (e.g. remote CSV/DB) is unreachable, so initialization never completes; tests querying lookups immediately after config load; racy lookup replacement where a delete lands between start and get.","solutions":["Call start() (and await its completion / use awaitInitialization) before invoking get().","Verify the lookup's underlying data source is reachable so start() can finish populating the cache.","Check lookup manager logs for a failed start or an earlier close() on this extractor ID; re-announce the lookup.","In code, guard with isStarted()/lifecycle checks before calling get()."],"exampleFix":"// before\nLookupExtractor lookup = factory.get();\n// after\nif (!factory.start()) { throw new ISE(\"lookup %s failed to start\", id); }\nfactory.awaitInitialization();\nLookupExtractor lookup = factory.get();","handlingStrategy":"validation","validationCode":"// java\nif (!factory.isStarted()) { factory.start(); }\n// await initialization before get()\nfactory.awaitInitialization(clock, 30_000);","typeGuard":null,"tryCatchPattern":"// java\ntry { LookupExtractor l = factory.get(); }\ncatch (IllegalStateException e) {\n  if (e.getMessage().startsWith(\"Factory [\") ) { /* restart/await start */ }\n}","preventionTips":["Always awaitInitialization after start() before serving lookups.","Ensure lookup data sources are reachable at startup.","Watch logs for failed start() on namespace lookups."],"tags":["lookup","lifecycle","cache-scheduler","race-condition"],"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"}