elastic/elasticsearch · error · IllegalArgumentException

Method reference passed to 'calling()' does not belong to {}

Error message

Method reference passed to 'calling()' does not belong to {} or one of its subclasses.

What it means

Thrown by ClassMethodBuilder.assertImplementationClass when a method reference passed to the 'calling()' entitlement builder does not belong to the expected class or a subclass. The check loads the implClassName and verifies clazz is assignable from it; if not, the rule was built against the wrong type and would never match at runtime.

Source

Thrown at libs/entitlement/src/main/java/org/elasticsearch/entitlement/rules/ClassMethodBuilder.java:1184

                "Proxy fallback only supports instance method references; no method was invoked on the proxy for "
                    + clazz.getName()
                    + ". If this is a static method reference, resolution must use SerializedLambda."
            );
        }
        return methodKeyFromMethod(holder.recordedMethod);
    }

    private static MethodKey methodKeyFromMethod(Method method) {
        String className = method.getDeclaringClass().getName().replace(".", "/");
        String methodName = method.getName();
        List<String> parameterTypes = Arrays.stream(method.getParameterTypes()).map(TypeUtils::getParameterTypeName).toList();
        return new MethodKey(className, methodName, parameterTypes);
    }

    private static void assertImplementationClass(Class<?> clazz, String implClassName) throws ClassNotFoundException {
        Class<?> implClass = Class.forName(implClassName.replace("/", "."));
        if (implClass.isAssignableFrom(clazz) == false) {
            throw new IllegalArgumentException(
                "Method reference passed to 'calling()' does not belong to " + clazz.getName() + " or one of its subclasses."
            );
        }
    }

    @SuppressForbidden(reason = "relies on reflection")
    private static Class<?> resolveDeclaringClass(Class<?> clazz, String methodName, Class<?>... args) throws NoSuchMethodException {
        if ("<init>".equals(methodName)) {
            return clazz;
        }
        Class<?>[] resolvedArgs = Arrays.stream(args).map(TypeUtils::toPrimitive).toArray(Class[]::new);
        return clazz.getMethod(methodName, resolvedArgs).getDeclaringClass();
    }

    @SuppressForbidden(reason = "relies on reflection")
    private static void validateConstructorExists(Class<?> clazz, Class<?>... args) {
        Class<?>[] resolvedArgs = Arrays.stream(args).map(TypeUtils::toPrimitive).toArray(Class[]::new);
        try {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Update the method reference so it belongs to the class named in the error or one of its subclasses.
  2. Re-check the entitlement rule definition and align the target class with the method reference's declaring class.
  3. If the class was renamed, update the rule to reference the new name.

Example fix

// before: rule targets ClassA but reference is from ClassB
builder.calling(ClassB::doWork);

// after: align the reference to the rule's target class
builder.calling(ClassA::doWork);
Defensive patterns

Strategy: type-guard

Validate before calling

// Validate the declaring class before registering the rule
Class<?> expected = Class.forName(implClassName.replace("/", "."));
if (!expected.isAssignableFrom(declaredClass)) {
  throw new IllegalArgumentException("method reference class mismatch");
}

Type guard

boolean ruleClassMatches(Class<?> ruleTarget, Class<?> refDeclaring) {
  return ruleTarget.isAssignableFrom(refDeclaring);
}

Prevention

When it happens

Trigger: assertImplementationClass(clazz, implClassName) calls Class.forName(implClassName) then implClass.isAssignableFrom(clazz) returns false. This happens when the method reference's declaring class is unrelated to the class the rule targets.

Common situations: Copy-pasting an entitlement rule and forgetting to update the target class; passing a helper class's method reference where the rule expects the target class; refactor renamed a class but the entitlement rule was not updated.

Related errors


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