quarkusio/quarkus · error · DefinitionException

Invalid injection of Interceptor<T> bean, can only be used i

Error message

Invalid injection of Interceptor<T> bean, can only be used in interceptors but was detected in: ${injectionPointInfo.getTargetInfo()}

What it means

Per the CDI 4.1 bean-metadata rules, an Interceptor<T> instance may only be injected into an interceptor (or decorator) instance. ArC detects an Interceptor<T> injection point into a regular managed bean, synthetic bean, or producer method at build time and throws this DefinitionException.

Source

Thrown at independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Injection.java:72

    private static Injection forSynthetic(Iterable<TypeAndQualifiers> injectionPoints, BeanType beanType) {
        List<InjectionPointInfo> ret = new ArrayList<>();
        for (TypeAndQualifiers injectionPoint : injectionPoints) {
            InjectionPointInfo ip = InjectionPointInfo.fromSyntheticInjectionPoint(injectionPoint);
            validateInjections(ip, beanType);
            ret.add(ip);
        }
        return new Injection(null, ret);
    }

    private static void validateInjections(InjectionPointInfo injectionPointInfo, BeanType beanType) {
        // Mostly validation related to Bean metadata injection restrictions
        // see https://jakarta.ee/specifications/cdi/4.1/jakarta-cdi-spec-4.1.html#bean_metadata
        if (beanType == BeanType.MANAGED_BEAN || beanType == BeanType.SYNTHETIC_BEAN || beanType == BeanType.PRODUCER_METHOD) {
            // If an Interceptor<T> instance is injected into a bean instance other than an interceptor instance,
            // the container automatically detects the problem and treats it as a definition error.
            if (injectionPointInfo.getType().name().equals(DotNames.INTERCEPTOR_BEAN)) {
                throw new DefinitionException("Invalid injection of Interceptor<T> bean, can only be used in interceptors " +
                        "but was detected in: " + injectionPointInfo.getTargetInfo());
            }

            // If a Bean instance with qualifier @Intercepted is injected into a bean instance other than an interceptor
            // instance, the container automatically detects the problem and treats it as a definition error.
            if (injectionPointInfo.getType().name().equals(DotNames.BEAN)
                    && injectionPointInfo.getRequiredQualifier(DotNames.INTERCEPTED) != null) {
                throw new DefinitionException(
                        "Invalid injection of @Intercepted Bean<T>, can only be injected into interceptors " +
                                "but was detected in: " + injectionPointInfo.getTargetInfo());
            }

            // If a Decorator<T> instance is injected into a bean instance other than a decorator instance,
            // the container automatically detects the problem and treats it as a definition error.
            if (injectionPointInfo.getType().name().equals(DotNames.DECORATOR)) {
                throw new DefinitionException("Invalid injection of Decorator<T> bean, can only be used in decorators " +
                        "but was detected in: " + injectionPointInfo.getTargetInfo());
            }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Move the Interceptor<T> injection point into an interceptor or decorator class
  2. If you only need interceptor behavior, apply the interceptor binding annotation to the bean instead of injecting Interceptor<T>
  3. Remove the injection point entirely if the metadata is not actually needed

Example fix

// before
@ApplicationScoped
class MyService { @Inject Interceptor<MyService> interceptor; }
// after
class MyServiceInterceptor { @Inject Interceptor<Object> interceptor; }
Defensive patterns

Strategy: validation

Validate before calling

boolean ok = java.util.Arrays.stream(MyBean.class.getDeclaredFields())
    .noneMatch(f -> f.getType().getName().equals("jakarta.enterprise.inject.spi.Interceptor"));

Prevention

When it happens

Trigger: Adding an @Inject Interceptor<MyType> (or Instance<Interceptor<...>>) field/parameter/constructor argument to a normal @ApplicationScoped/@RequestScoped bean or producer method instead of to an interceptor class.

Common situations: Trying to programmatically inspect or invoke interceptors from business code; copying interceptor metadata injection code out of an interceptor class into a service bean.

Related errors


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