quarkusio/quarkus · error · RuntimeException

Unable to determine if the '${unsecuredMethod}' method shoul

Error message

Unable to determine if the '${unsecuredMethod}' method should inherit security annotation of the '${securedMethod}' method (generics not supported yet)

What it means

When a class implements an interface whose method carries a security annotation, Quarkus checks whether the implementing method should inherit that annotation. If the methods involve generics/type variables, the Jandex-based check cannot decide safely and throws RuntimeException rather than silently skipping the check.

Source

Thrown at extensions/security/spi/src/main/java/io/quarkus/security/spi/SecurityTransformerBuildItem.java:232

                && securedMethod.parametersCount() == unsecuredMethod.parametersCount()) {
            if (securedMethod.parametersCount() == 0) {
                return true;
            }
            var securedMethodParams = securedMethod.parameterTypes();
            if (hasNoTypeVariable(securedMethodParams)) {
                // no type variables
                return securedMethodParams.equals(unsecuredMethod.parameterTypes());
            } else {
                // methods with type variables are currently not supported
                throw newUnableToDetermineIfSecuredException(securedMethod, unsecuredMethod);
            }
        }
        return false;
    }

    private static RuntimeException newUnableToDetermineIfSecuredException(MethodInfo securedMethod,
            MethodInfo unsecuredMethod) {
        throw new RuntimeException(
                "Unable to determine if the '%s' method should inherit security annotation of the '%s' method (generics not supported yet)"
                        .formatted(toString(unsecuredMethod), toString(securedMethod)));
    }

    private static boolean hasNoTypeVariable(List<Type> method) {
        return method.stream().noneMatch(t -> {
            if (t.kind() == TYPE_VARIABLE || t.kind() == Type.Kind.TYPE_VARIABLE_REFERENCE
                    || t.kind() == Type.Kind.UNRESOLVED_TYPE_VARIABLE || t.kind() == Type.Kind.WILDCARD_TYPE) {
                return true;
            }
            return t.kind() == PARAMETERIZED_TYPE && !hasNoTypeVariable(t.asParameterizedType().arguments());
        });
    }

    private static Collection<ClassInfo> collectParentInterfaces(HashSet<ClassInfo> possiblySecuredInterfaces,
            Set<DotName> securedInterfaceAnnotations, IndexView index) {
        // this should avoid something like jakarta.data.repository.DataRepository
        // because we only need inspect classes added by user for security annotations

View on GitHub (pinned to e1c734241f)

Solutions

  1. Re-annotate the implementing method directly with the security annotation instead of relying on inheritance from the generic interface method.
  2. Remove type variables from the method signature (use concrete types) so the inheritance check can succeed.
  3. Wrap the annotated generic method in a non-generic delegating bean that carries the security annotation.
  4. Avoid securing the interface method at all; secure the implementation.

Example fix

// before
interface Repo<T> { @RolesAllowed("admin") T find(long id); }
class UserRepo implements Repo<User> { public User find(long id) {...} }

// after
class UserRepo implements Repo<User> {
    @RolesAllowed("admin")
    public User find(long id) {...}
}
Defensive patterns

Strategy: validation

Validate before calling

boolean genericsFree(java.lang.reflect.Method m) {
    return m.getTypeParameters().length == 0
        && java.util.Arrays.stream(m.getGenericParameterTypes()).noneMatch(t -> t instanceof java.lang.reflect.TypeVariable)
        && !(m.getGenericReturnType() instanceof java.lang.reflect.TypeVariable);
}

Prevention

When it happens

Trigger: A class implements/extends an interface with a @RolesAllowed/@Authenticated-annotated method where the implementation or interface method uses generic type parameters or type variables, defeating the hasNoTypeVariable checks during isImplementingSecuredMethod.

Common situations: Generic repositories/services like interface Repo<T> { @RolesAllowed("admin") T find(long id); } implemented by a CDI bean; frameworks generating generic implementations; upgrading Quarkus surfaces the previously-unsound generics case.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/4138b253eb1dbd40. Report an issue: GitHub.