elastic/elasticsearch · critical · RuntimeException
Failed to transform JDK classes for entitlements
Error message
Failed to transform JDK classes for entitlements
What it means
Thrown by DynamicInstrumentation when the bytecode transformation of JDK classes for entitlement instrumentation reports errors after retransformation. The transformer is asked to retransform classes one at a time for diagnostics; if transformer.hadErrors() is still true after the loop, a RuntimeException is thrown. This indicates the entitlement agent could not instrument the JDK classes it needs to police.
Source
Thrown at libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/DynamicInstrumentation.java:88
inst.addTransformer(transformer, true);
var classesToRetransform = findClassesToRetransform(inst, inst.getAllLoadedClasses(), classesWithDirectRules);
try {
inst.retransformClasses(classesToRetransform);
} catch (VerifyError e) {
// Turn on verification and try to retransform one class at the time to get detailed diagnostic
transformer.enableClassVerification();
for (var classToRetransform : classesToRetransform) {
inst.retransformClasses(classToRetransform);
}
// We should have failed already in the loop above, but just in case we did not, rethrow.
throw e;
}
if (transformer.hadErrors()) {
throw new RuntimeException("Failed to transform JDK classes for entitlements");
}
}
/**
* Finds already-loaded classes that need retransformation, including subtypes of classes with rules.
* Performs a full BFS traversal of each class's hierarchy to check for inherited rules,
* so visitation order does not matter.
*/
private static Class<?>[] findClassesToRetransform(Instrumentation inst, Class<?>[] loadedClasses, Set<String> classesWithDirectRules) {
List<Class<?>> retransform = new ArrayList<>();
for (Class<?> loadedClass : loadedClasses) {
if (loadedClass.isHidden()) {
continue;
}
String internalName = loadedClass.getName().replace('.', '/');
boolean directMatch = classesWithDirectRules.contains(internalName);
if (directMatch == false) {
ClassLoader cl = loadedClass.getClassLoader();View on GitHub (pinned to db6a809a66)
Solutions
- Use a JDK version that is supported by this Elasticsearch build (check the compatibility matrix).
- Remove or disable other javaagents that instrument JDK internals (profilers, coverage, APM) and retry.
- Capture the detailed per-class diagnostic printed during the verification-enabled retry loop to identify the offending class, then report or work around it.
- Update the Elasticsearch distribution so the bundled entitlement agent matches the running JDK.
Example fix
// before: -javaagent:profiler.jar AND entitlement agent conflict // after: run without the conflicting agent java -jar es.jar // no extra -javaagent
Defensive patterns
Strategy: try-catch
Validate before calling
// Probe for conflicting agents and supported JDK before bootstrap
for (String a : ManagementFactory.getRuntimeMXBean().getInputArguments()) {
if (a.startsWith("-javaagent:")) {
// known-OK agents may be allow-listed here
}
} Try / catch
try {
EntitlementBootstrap.initialize(...);
} catch (RuntimeException e) {
if (e.getMessage().equals("Failed to transform JDK classes for entitlements")) {
// capture transformer diagnostic, remove conflicting -javaagent, or align JDK version
}
throw e;
} Prevention
- Run only the bundled entitlement agent; remove profiler/APM/coverage javaagents that instrument JDK internals.
- Use a JDK version listed in the ES compatibility matrix.
When it happens
Trigger: During installEntitlementInstrumentation, inst.retransformClasses throws; the catch enables class verification and retries each class individually, then if transformer.hadErrors() returns true, this exception fires. Causes include unsupported bytecode versions, conflicts with another agent, or a JDK internals layout the transformer cannot handle.
Common situations: Running on a JDK version whose internals differ from what the entitlement agent was built for; another javaagent (e.g. APM, profiler) is also instrumenting the same JDK classes and conflicts; a modular JDK denies reflective access the transformer relies on.
Related errors
- Unable to attach entitlement agent [{}] after [{}ms]
- Directory for entitlement jar does not exist: {}
- Expected one jar in {}; found {}
- Failed to list entitlement jars in: {}
- Error patching JAR [%s]: SHA256 digest mismatch (%s). This J
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/f9d0d47aeba37d12.
Report an issue: GitHub.