{"record":{"id":"e81f879137235ddd","repo":"apache/druid","slug":"extension-s-depends-on-s-which-is-not-a-vali","errorCode":null,"errorMessage":"Extension [%s] depends on [%s] which is not a valid extension or not loaded.","messagePattern":"Extension \\[(.+?)\\] depends on \\[(.+?)\\] which is not a valid extension or not loaded\\.","errorType":"validation","errorClass":"RE","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/guice/ExtensionsLoader.java","lineNumber":282,"sourceCode":"\n      return classLoader;\n    }\n  }\n\n  private StandardURLClassLoader makeClassLoaderWithDruidExtensionDependencies(File extension, boolean useExtensionClassloaderFirst, List<String> extensionDependencyStack)\n  {\n    Optional<DruidExtensionDependencies> druidExtensionDependenciesOptional = getDruidExtensionDependencies(extension);\n    List<String> druidExtensionDependenciesList = druidExtensionDependenciesOptional.isPresent()\n        ? druidExtensionDependenciesOptional.get().getDependsOnDruidExtensions()\n        : ImmutableList.of();\n\n    List<ClassLoader> extensionDependencyClassLoaders = new ArrayList<>();\n    for (String druidExtensionDependencyName : druidExtensionDependenciesList) {\n      Optional<File> extensionDependencyFileOptional = Arrays.stream(getExtensionFilesToLoad())\n          .filter(file -> file.getName().equals(druidExtensionDependencyName))\n          .findFirst();\n      if (!extensionDependencyFileOptional.isPresent()) {\n        throw new RE(\n            StringUtils.format(\n                \"Extension [%s] depends on [%s] which is not a valid extension or not loaded.\",\n                extension.getName(),\n                druidExtensionDependencyName\n            )\n        );\n      }\n      File extensionDependencyFile = extensionDependencyFileOptional.get();\n      if (extensionDependencyStack.contains(extensionDependencyFile.getName())) {\n        extensionDependencyStack.add(extensionDependencyFile.getName());\n        throw new RE(\n            StringUtils.format(\n                \"Extension [%s] has a circular druid extension dependency. Dependency stack [%s].\",\n                extensionDependencyStack.get(0),\n                extensionDependencyStack\n            )\n        );\n      }","sourceCodeStart":264,"sourceCodeEnd":300,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/guice/ExtensionsLoader.java#L264-L300","documentation":"Druid extensions can declare dependencies on other Druid extensions via druid.extension.dependencies in their dependencies JSON. getClassLoaderForExtension() builds a classloader chain, and this RE is thrown when a declared dependency's name does not match any extension directory currently slated for loading.","triggerScenarios":"Extension A's druid-extension-dependencies.json lists extension B in druid.extension.dependencies, but B is absent from the extensions directory or excluded from the loadList when getClassLoaderForExtension(A) is invoked.","commonSituations":"Installing an extension but forgetting its required companion extension; loadList omits a transitive dependency; upgrading one extension while its dependency was removed; typos in the dependencies JSON.","solutions":["Add the missing dependency extension to the extensions directory","Include the dependency in druid.extensions.loadList so it is loaded","Fix the druid.extension.dependencies entry in the extension's druid-extension-dependencies.json if it names a nonexistent extension","Remove the dependency declaration if the newer version of the extension no longer needs it"],"exampleFix":"// before\n-Ddruid.extensions.loadList=\"[\\\"druid-kerberos\\\"]\"\n// after\n-Ddruid.extensions.loadList=\"[\\\"druid-kerberos\\\", \\\"druid-basic-security\\\"]\"","handlingStrategy":"validation","validationCode":"Set<String> loaded = new HashSet<>(loadList);\nfor (String dep : declaredDeps(extension)) {\n  if (!loaded.contains(dep)) {\n    throw new IllegalStateException(extension + \" needs unloaded extension \" + dep);\n  }\n}","typeGuard":null,"tryCatchPattern":"try { getClassLoaderForExtension(ext); } catch (RE e) {\n  if (e.getMessage().contains(\"not a valid extension or not loaded\")) { loadDependency(ext, e); }\n  throw e;\n}","preventionTips":["Read each extension's druid-extension-dependencies.json and include all entries in loadList","Keep companion extensions installed together as a bundle","After removing an extension, grep other extensions' dependency manifests for it"],"tags":["extensions","dependency","classloader"],"backgroundTag":"missing-dependency","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}