quarkusio/quarkus · error · DefinitionException

Invalid injection of @Intercepted Bean<T>, can only be injec

Error message

Invalid injection of @Intercepted Bean<T>, can only be injected into interceptors but was detected in: ${injectionPointInfo.getTargetInfo()}

What it means

Per CDI 4.1, a Bean instance qualified @Intercepted may only be injected into an interceptor instance. ArC's build-time validation detects such an injection into a regular managed bean, synthetic bean, or producer method and throws this DefinitionException.

Source

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

        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());
            }

            // If a Bean instance with qualifier @Decorated 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.BEAN)
                    && injectionPointInfo.getRequiredQualifier(DotNames.DECORATED) != null) {
                throw new DefinitionException(
                        "Invalid injection of @Decorated Bean<T>, can only be injected into decorators " +
                                "but was detected in: " + injectionPointInfo.getTargetInfo());

View on GitHub (pinned to e1c734241f)

Solutions

  1. Move the @Intercepted Bean<T> injection into an interceptor class
  2. Drop the @Intercepted qualifier if you only need Bean<T> metadata (plain Bean<T> injection into beans is allowed with correct type rules)
  3. Use Instance<T> or programmatic lookup instead if the goal is obtaining the bean instance

Example fix

// before
@ApplicationScoped class Svc { @Inject @Intercepted Bean<Svc> self; }
// after
class SvcInterceptor { @Inject @Intercepted Bean<Object> interceptedBean; }
Defensive patterns

Strategy: validation

Validate before calling

boolean ok = java.util.Arrays.stream(MyBean.class.getDeclaredFields())
    .noneMatch(f -> f.isAnnotationPresent(jakarta.enterprise.inject.Intercepted.class));

Prevention

When it happens

Trigger: Injecting a field like @Inject @Intercepted Bean<MyBean> bean into a normal (non-interceptor) bean, synthetic bean, or producer method.

Common situations: Attempting to access the intercepted instance metadata from application code; mimicking examples written for interceptor classes; writing generic cross-cutting helpers that read bean metadata.

Related errors


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