elastic/elasticsearch · error · IllegalArgumentException
error patching [%s]: the jar does not contain [%s]
Error message
error patching [%s]: the jar does not contain [%s]
What it means
Thrown by Utils.patchJar after iterating all JAR entries: the classPatchers map (built from the requested PatcherInfo collection) still has leftover entries, meaning the input JAR did not contain class entries matching the patcher jar-entry names. The patcher targets specific class paths inside the JAR (e.g. 'com/foo/Bar.class') and cannot proceed if those entries are absent, because patching nothing would silently produce an unpatched JAR.
Source
Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/Utils.java:153
throw new RuntimeException(ex);
}
if (mismatchedClasses.isEmpty() == false) {
throw new IllegalArgumentException(
String.format(
Locale.ROOT,
"""
Error patching JAR [%s]: SHA256 digest mismatch (%s). This JAR was updated to a version that contains different \
classes, for which this patcher was not designed. Please check if the patcher still \
applies correctly, and update the SHA256 digest(s).""",
inputFile.getName(),
mismatchedClasses.stream().map(MismatchInfo::toString).collect(Collectors.joining())
)
);
}
if (classPatchers.isEmpty() == false) {
throw new IllegalArgumentException(
String.format(
Locale.ROOT,
"error patching [%s]: the jar does not contain [%s]",
inputFile.getName(),
String.join(", ", classPatchers.keySet())
)
);
}
}
}
View on GitHub (pinned to db6a809a66)
Solutions
- Open the input JAR with 'jar tf <file>.jar | grep <className>' and find the actual entry name for the class you intend to patch.
- Update the PatcherInfo jarEntryName in the patch configuration (e.g. the JarRelocation/Patches block in build-conventions or the module's build.gradle) to match the real entry path.
- If the class was genuinely removed in the new dependency version, remove the now-obsolete PatcherInfo entry and verify the patch is no longer needed.
- Pin the dependency to the version the patcher was written for until the patcher is updated.
Example fix
// before: patcher references an entry that no longer exists
new PatcherInfo("com/fasterxml/jackson/databind/ObjectMapper.class", sha, visitor)
// after: confirm actual entry name in the upgraded JAR and update
// run: jar tf jackson-databind-2.17.0.jar | grep ObjectMapper
new PatcherInfo("com/fasterxml/jackson/databind/ObjectMapper.class", newSha, visitor) Defensive patterns
Strategy: validation
Validate before calling
// Before calling Utils.patchJar, confirm every patcher entry exists in the JAR
import java.util.jar.JarFile;
import java.util.HashSet;
import java.util.Set;
void verifyPatchTargets(File inputJar, Collection<PatcherInfo> patchers) throws IOException {
Set<String> entries;
try (JarFile jf = new JarFile(inputJar)) {
entries = new HashSet<>(jf.stream().map(JarEntry::getName).toList());
}
var missing = patchers.stream()
.map(PatcherInfo::jarEntryName)
.filter(e -> !entries.contains(e))
.toList();
if (!missing.isEmpty()) {
throw new IllegalStateException(
"JAR " + inputJar + " is missing patch targets: " + missing
+ ". Available entries containing the class name: "
+ entries.stream().filter(e -> e.contains(missing.get(0).replace('/', '.').replace(".class",""))).toList()
);
}
}
// call: verifyPatchTargets(inputFile, patchers); Prevention
- When upgrading a patched dependency, run 'jar tf <new>.jar | grep <ClassName>' and diff against the patcher's jarEntryName before building.
- Keep patcher configurations (PatcherInfo entries) in a single discoverable location (e.g. build-conventions) so upgrades surface all affected patchers at once.
- Add a CI step that verifies all patch target entry names exist in the resolved JAR before the patch task runs.
When it happens
Trigger: A dependency JAR is upgraded to a version where the target class was renamed, moved to a different package, or removed entirely; or a PatcherInfo was configured with a typo'd jarEntryName that does not correspond to any entry in the JAR being patched.
Common situations: Bumping a third-party dependency version (e.g. jackson, lucene) in build-conventions or a module's build.gradle without updating the corresponding patch definitions; the upstream library refactored or deleted the patched class. Less commonly, a patcher was authored against a wrong or typo'd entry name from the start.
Related errors
- Error patching JAR [%s]: SHA256 digest mismatch (%s). This J
- Unsupported classpath element: {}
- Build directory unknown to gradle: {}
- Failed to patch archive
- Failed to unpack {} with checksum {}
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/66be363db00c5bcc.
Report an issue: GitHub.