quarkusio/quarkus · error · IllegalArgumentException

No interceptor bindings

Error message

No interceptor bindings

What it means

resolveInterceptors requires at least one interceptor binding annotation. With zero bindings there is nothing meaningful to match interceptors against, so Arc throws IllegalArgumentException immediately (after the early 'no interceptors registered' fast path). This guards BeanManager.resolveInterceptors(InterceptionType, Annotation...) usage.

Source

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

        for (InjectableObserverMethod<?> observer : observers) {
            if (EventTypeAssignabilityRules.instance().matches(observer.getObservedType(), eventTypes)) {
                if (observer.getObservedQualifiers().isEmpty()
                        || registeredQualifiers.isSubset(observer.getObservedQualifiers(), eventQualifiers)) {
                    resolvedObservers.add((InjectableObserverMethod<? super T>) observer);
                }
            }
        }
        // Observers with smaller priority values are called first
        Collections.sort(resolvedObservers);
        return resolvedObservers;
    }

    List<Interceptor<?>> resolveInterceptors(InterceptionType type, Annotation... interceptorBindings) {
        if (interceptors.isEmpty()) {
            return Collections.emptyList();
        }
        if (interceptorBindings.length == 0) {
            throw new IllegalArgumentException("No interceptor bindings");
        }
        registeredInterceptorBindings.verify(interceptorBindings);
        List<Interceptor<?>> interceptors = new ArrayList<>();
        List<Annotation> bindings = new ArrayList<>();
        for (Annotation binding : interceptorBindings) {
            bindings.add(binding);
            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;
    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Pass at least one interceptor binding annotation (e.g. @Transactional.Literal.INSTANCE or a custom binding literal)
  2. Guard the call: if bindings.length == 0 return an empty list instead of calling resolveInterceptors
  3. Check the annotations collected reflectively actually include @InterceptorBinding-annotated annotations

Example fix

// before
manager.resolveInterceptors(InterceptionType.AROUND_INVOKE); // empty

// after
manager.resolveInterceptors(InterceptionType.AROUND_INVOKE,
    MyBinding.Literal.INSTANCE);
Defensive patterns

Strategy: validation

Validate before calling

if (bindings == null || bindings.length == 0) {
    throw new IllegalArgumentException("At least one interceptor binding is required");
}
List<Interceptor<?>> its = bm.resolveInterceptors(InterceptionType.AROUND_INVOKE, bindings);

Try / catch

try {
    return bm.resolveInterceptors(type, bindings);
} catch (IllegalArgumentException e) {
    LOGGER.warn("No interceptor bindings supplied");
    return List.of();
}

Prevention

When it happens

Trigger: Calling beanManager.resolveInterceptors(InterceptionType.AROUND_INVOKE) or with an empty bindings array; programmatically building an interceptor chain and passing an empty annotation list; a bug in code that filters bindings down to zero.

Common situations: Custom AOP/extension code introspecting interceptors; dynamic proxies built by hand; reflection collecting annotations from a member that actually has none.

Related errors


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