quarkusio/quarkus · error · RuntimeException

Only one of the '<annotations>' annotations can be applied o

Error message

Only one of the '<annotations>' annotations can be applied on the '<class>' class

What it means

A class (endpoint) may only carry one of the mutually exclusive HTTP security annotations such as @Basic, @Form, @BearerAuth, etc. Combining two of these on the same class is ambiguous — only one auth mechanism can be selected per endpoint — so the build fails. @CodeFlow and @Tenant are the exceptions and may be combined with others.

Source

Thrown at extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/HttpSecurityProcessor.java:858

                for (AnnotationInstance annotation : annotationInstances) {
                    if (annotation.target().kind() != appliesTo) {
                        continue;
                    }
                    if (annotation.target().kind() == AnnotationTarget.Kind.CLASS) {
                        ClassInfo interceptedClass = annotation.target().asClass();
                        if (interceptedClass.isAnnotation()) {
                            // currently we don't support meta-annotations
                            // this is the easiest way to avoid detecting @HttpAuthenticationMechanism on @BasicAuthentication
                            continue;
                        }

                        if (hasClassLevelSecurity.test(interceptedClass)) {
                            // endpoint can only be annotated with one of @Basic, @Form, ...
                            // however combining @CodeFlow and @Tenant is supported
                            var appliedBindings = cache.computeIfAbsent(interceptedClass, a -> new ArrayList<>());
                            if (appliedBindings.contains(interceptorBinding)) {
                                if (!interceptorBinding.allowToRepeatThisInterceptorBinding()) {
                                    throw new RuntimeException(
                                            "Only one of the '%s' annotations can be applied on the '%s' class".formatted(
                                                    Arrays.toString(interceptorBinding.getAnnotationBindings()),
                                                    interceptedClass));
                                }
                            } else {
                                appliedBindings.add(interceptorBinding);
                            }

                            // don't apply security interceptor on individual methods, but on the class-level instead
                            bindingValueToInterceptedClasses
                                    .computeIfAbsent(interceptorBinding.getBindingValue(annotation, annotationBinding,
                                            interceptedClass), s -> new HashSet<>())
                                    .add(interceptedClass.name().toString());
                            continue;
                        }

                        for (MethodInfo method : interceptedClass.methods()) {
                            if (hasProperEndpointModifiers(method)) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Keep only one auth mechanism annotation on the class and delete the other
  2. If both behaviors are needed, use configuration-based policy (quarkus.http.auth.permission) instead
  3. Move the mechanism choice to individual endpoint methods if different endpoints need different mechanisms

Example fix

// before
@Basic
@Form
public class UserResource { ... }
// after
@Basic
public class UserResource { ... }
Defensive patterns

Strategy: validation

Validate before calling

long count = Arrays.stream(Resource.class.getAnnotations())
    .map(Annotation::annotationType)
    .filter(t -> Set.of(Basic.class, Form.class, BearerAuth.class).contains(t))
    .count();
if (count > 1) throw new IllegalStateException("Only one auth mechanism annotation allowed on class");

Prevention

When it happens

Trigger: Annotating the same endpoint class with two different auth mechanism annotations (e.g. both @Basic and @Form), where the binding does not allow repetition.

Common situations: Merging code from branches where different developers chose different mechanisms; copy-pasting security annotations between classes without removing the old one; misunderstanding which annotations are mutually exclusive.

Related errors


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