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

  1. Use a JDK version that is supported by this Elasticsearch build (check the compatibility matrix).
  2. Remove or disable other javaagents that instrument JDK internals (profilers, coverage, APM) and retry.
  3. Capture the detailed per-class diagnostic printed during the verification-enabled retry loop to identify the offending class, then report or work around it.
  4. 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

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


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/f9d0d47aeba37d12. Report an issue: GitHub.