elastic/elasticsearch · critical · IllegalStateException
jar hell! class: {clazz} exists multiple times in jar: {jarp
Error message
jar hell!
class: {clazz}
exists multiple times in jar: {jarpath} !!!!!!!!! What it means
Thrown by JarHell.checkClass when the exact same fully-qualified class name appears more than once inside the SAME single JAR/URL (previous.equals(jarpath) is true). The zip format technically allows duplicate entries, but Elasticsearch treats this as jar hell because it makes class loading ambiguous. The message names the class and the single jar path containing the duplicates.
Source
Thrown at libs/core/src/main/java/org/elasticsearch/jdk/JarHell.java:297
if (Runtime.version().feature() < version.feature()) {
throw new IllegalStateException(
String.format(Locale.ROOT, "%s requires Java %s:, your system: %s", resource, targetVersion, Runtime.version().toString())
);
}
}
private static void checkClass(Map<String, Path> clazzes, String clazz, Path jarpath) {
if (clazz.equals("module-info") || clazz.endsWith(".module-info")) {
// Ignore jigsaw module descriptions
return;
}
Path previous = clazzes.put(clazz, jarpath);
if (previous != null) {
if (previous.equals(jarpath)) {
// throw a better exception in this ridiculous case.
// unfortunately the zip file format allows this buggy possibility
// UweSays: It can, but should be considered as bug :-)
throw new IllegalStateException(
"jar hell!"
+ System.lineSeparator()
+ "class: "
+ clazz
+ System.lineSeparator()
+ "exists multiple times in jar: "
+ jarpath
+ " !!!!!!!!!"
);
} else {
throw new IllegalStateException(
"jar hell!"
+ System.lineSeparator()
+ "class: "
+ clazz
+ System.lineSeparator()
+ "jar1: "
+ previousView on GitHub (pinned to db6a809a66)
Solutions
- Rebuild the named JAR with a deduplicating archive tool (e.g. 'jar' or 'zip' that skips existing entries).
- Inspect the JAR for duplicate entries: 'unzip -l <jarpath> | sort | uniq -d' and remove the offending duplicates.
- If a shading/assembly plugin produced it, configure it to deduplicate or use 'relocate' to rename colliding classes.
- Re-download or reinstall the plugin/module that shipped the malformed JAR.
Example fix
// before: jar contains duplicate com/foo/Bar.class // unzip -l bad.jar | grep com/foo/Bar.class -> two entries // after: rebuild, deduplicating entries zip -d bad.jar 'com/foo/Bar.class' # remove dup jar uf clean.jar -C classes . # repackage cleanly
Defensive patterns
Strategy: validation
Validate before calling
// Before adding a jar to the classpath, assert no internal duplicate entries
import java.util.jar.*;
import java.util.*;
void assertNoInternalDuplicates(Path jar) throws IOException {
try (var jf = new JarFile(jar.toFile())) {
Set<String> seen = new HashSet<>();
var e = jf.entries();
while (e.hasMoreElements()) {
String name = e.nextElement().getName();
if (name.endsWith(".class") && !seen.add(name)) {
throw new IllegalStateException(jar + " has duplicate entry " + name);
}
}
}
} Prevention
- Use deduplicating archive tooling when assembling fat/shaded jars.
- Add a build check that fails if any jar on the output classpath has duplicate entries.
- Never concatenate zip files manually.
When it happens
Trigger: A JAR on the classpath contains two entries with the identical .class path (e.g. someone zipped the same class file twice, or merged two jars with 'jar uf' without dedup). checkClass() puts the class into the clazzes map keyed by name; on the second insertion the previous Path equals the current jarpath, triggering this branch.
Common situations: A build step merged jars with a tool that does not deduplicate entries; a fat/shaded jar was built with a plugin that emitted duplicate class entries; a manually repackaged jar concatenated zip entries; a corrupted download.
Related errors
- jar hell! class: {clazz} jar1: {previous} jar2: {jarpath}
- Classpath should not contain empty elements! (outdated shell
- jar hell! duplicate jar [{element}] on classpath: {classPath
- jar hell! duplicate jar on classpath: {path}
- %s requires Java %s:, your system: %s
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/37c793e6d4290026.
Report an issue: GitHub.