quarkusio/quarkus · error · IllegalArgumentException

The set of bean types must not be empty

Error message

The set of bean types must not be empty

What it means

resolveDecorators requires a non-empty set of bean types to match decorators against. Passing a null or empty Set gives decorators nothing to compare assignability with, so Arc throws IllegalArgumentException. Qualifiers default to @Default when omitted.

Source

Thrown at independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/ArcContainerImpl.java:927

            Set<Annotation> transitive = registeredInterceptorBindings.getTransitive(binding.annotationType());
            if (transitive != null) {
                bindings.addAll(transitive);
            }
        }
        for (InjectableInterceptor<?> interceptor : this.interceptors) {
            if (interceptor.intercepts(type) && hasAllInterceptionBindings(interceptor, bindings)) {
                interceptors.add(interceptor);
            }
        }
        return interceptors;
    }

    List<Decorator<?>> resolveDecorators(Set<Type> types, Annotation... qualifiers) {
        if (decorators.isEmpty()) {
            return Collections.emptyList();
        }
        if (Objects.requireNonNull(types).isEmpty()) {
            throw new IllegalArgumentException("The set of bean types must not be empty");
        }
        if (qualifiers == null || qualifiers.length == 0) {
            qualifiers = new Annotation[] { Default.Literal.INSTANCE };
        } else {
            registeredQualifiers.verify(qualifiers);
        }
        List<Decorator<?>> decorators = new ArrayList<>();
        for (InjectableDecorator<?> decorator : this.decorators) {
            if (decoratorMatches(decorator.getDelegateType(), decorator.getDelegateQualifiers(), types, Set.of(qualifiers))) {
                decorators.add(decorator);
            }
        }
        return decorators;
    }

    private boolean hasAllInterceptionBindings(InjectableInterceptor<?> interceptor, Iterable<Annotation> bindings) {
        // The method or constructor has all the interceptor bindings of the interceptor
        for (Annotation binding : interceptor.getInterceptorBindings()) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Populate the set with at least one Type (the bean class or interface) before calling
  2. Null/empty-check the types set in your calling code and short-circuit to an empty decorator list
  3. If deriving types from a bean, use bean.getTypes() which never returns empty for valid beans

Example fix

// before
manager.resolveDecorators(Set.of(), Default.Literal.INSTANCE);

// after
manager.resolveDecorators(Set.of(MyService.class), Default.Literal.INSTANCE);
Defensive patterns

Strategy: validation

Validate before calling

Objects.requireNonNull(types, "types");
if (types.isEmpty()) {
    return List.of(); // or throw with a clearer message
}
List<Decorator<?>> decorators = bm.resolveDecorators(types, qualifiers);

Try / catch

try {
    return bm.resolveDecorators(types, quals);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("bean types must not be empty")) {
        return List.of();
    } else throw e;
}

Prevention

When it happens

Trigger: Calling beanManager.resolveDecorators(Collections.emptySet(), qualifiers) or resolveDecorators(null, ...); building the types set from an object whose getTypes() returned empty due to an earlier resolution failure.

Common situations: Extension/tooling code computing decorator matches dynamically; a refactor that changed how the bean types set is assembled and accidentally yields an empty set.

Related errors


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