{"record":{"id":"b5d01823a0708813","repo":"apache/druid","slug":"the-extension-s-has-multiple-jars-s-s-wit","errorCode":null,"errorMessage":"The extension [%s] has multiple jars [%s] [%s] with dependencies in them. Each jar should be in a separate extension directory.","messagePattern":"The extension \\[(.+?)\\] has multiple jars \\[(.+?)\\] \\[(.+?)\\] with dependencies in them\\. Each jar should be in a separate extension directory\\.","errorType":"validation","errorClass":"RE","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/guice/ExtensionsLoader.java","lineNumber":389,"sourceCode":"    }\n  }\n\n  private Optional<DruidExtensionDependencies> getDruidExtensionDependencies(File extension)\n  {\n    final Collection<File> jars = FileUtils.listFiles(extension, new String[]{\"jar\"}, false);\n    DruidExtensionDependencies druidExtensionDependencies = null;\n    String druidExtensionDependenciesJarName = null;\n    for (File extensionFile : jars) {\n      try (JarFile jarFile = new JarFile(extensionFile.getPath())) {\n        Enumeration<JarEntry> entries = jarFile.entries();\n\n        while (entries.hasMoreElements()) {\n          JarEntry entry = entries.nextElement();\n          String entryName = entry.getName();\n          if (DRUID_EXTENSION_DEPENDENCIES_JSON.equals(entryName)) {\n            log.debug(\"Found extension dependency entry in jar [%s]\", extensionFile.getPath());\n            if (druidExtensionDependenciesJarName != null) {\n              throw new RE(\n                  StringUtils.format(\n                      \"The extension [%s] has multiple jars [%s] [%s] with dependencies in them. Each jar should be in a separate extension directory.\",\n                      extension.getName(),\n                      druidExtensionDependenciesJarName,\n                      jarFile.getName()\n                  )\n              );\n            }\n            druidExtensionDependencies = objectMapper.readValue(\n                jarFile.getInputStream(entry),\n                DruidExtensionDependencies.class\n            );\n            druidExtensionDependenciesJarName = jarFile.getName();\n          }\n        }\n      }\n      catch (IOException e) {\n        throw new RE(e, \"Failed to get dependencies for extension [%s]\", extension);","sourceCodeStart":371,"sourceCodeEnd":407,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/guice/ExtensionsLoader.java#L371-L407","documentation":"An extension directory may contain at most one jar carrying the druid-extension-dependencies.json descriptor. getDruidExtensionDependencies() scans jars in the extension directory and throws this RE if two different jars in the same extension both contain that entry, since it cannot decide which dependency manifest is authoritative.","triggerScenarios":"An extension directory contains 2+ jars that each bundle druid-extension-dependencies.json (usually from building/packaging the extension wrong or dropping multiple versions of the same jar into one extension folder).","commonSituations":"Copying an old and new version of an extension jar into the same directory; shading the dependency descriptor into multiple module jars of one extension; careless `cp *.jar extensions/myext/` after an upgrade.","solutions":["Remove the stale/duplicate jar so only one jar in the directory contains druid-extension-dependencies.json","Split the jars into separate extension directories, one per extension","Rebuild the extension so the dependency descriptor is only packaged in the primary jar","List the jar contents with `unzip -l *.jar | grep druid-extension-dependencies` to find the offending jars"],"exampleFix":"// before\nextensions/myext/myext-1.0.0.jar myext-1.1.0.jar  # both contain the descriptor\n// after\nextensions/myext/myext-1.1.0.jar","handlingStrategy":"validation","validationCode":"Set<String> descriptorJars = new HashSet<>();\nfor (File jar : new File(extDir).listFiles((d,n)->n.endsWith(\".jar\"))) {\n  try (JarFile jf = new JarFile(jar)) {\n    if (jf.getJarEntry(\"druid-extension-dependencies.json\") != null) {\n      if (!descriptorJars.add(jar.getName())) throw new IllegalStateException(\"Duplicate descriptor in \" + extDir);\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":"try { loadExtension(extDir); } catch (RE e) {\n  if (e.getMessage().contains(\"multiple jars\")) { dedupeExtensionJars(extDir); }\n  throw e;\n}","preventionTips":["Keep exactly one version of each extension jar per directory","Delete old jars on upgrade rather than copying alongside","Package the dependency descriptor in only one jar per extension build"],"tags":["extensions","packaging","duplicate"],"backgroundTag":"conflicting-config-options","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"}