quarkusio/quarkus · error · DefinitionException

Bean constructor must not have a @Disposes parameter:

Error message

Bean constructor must not have a @Disposes parameter: 

What it means

ArC (Quarkus's CDI implementation) throws this DefinitionException at build time when a bean's constructor has a parameter annotated with @Disposes. Per the CDI specification, @Disposes parameters belong only on disposer methods; a bean constructor can only have injection points. The check lives in Injection.forBean which validates all annotations on bean constructors.

Source

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

    static List<Injection> forBean(AnnotationTarget beanTarget, BeanInfo declaringBean, BeanDeployment beanDeployment,
            InjectionPointModifier transformer, BeanType beanType) {
        if (Kind.CLASS.equals(beanTarget.kind())) {
            List<Injection> injections = forClassBean(beanTarget.asClass(), beanTarget.asClass(), beanDeployment,
                    transformer, false, new HashSet<>());

            Set<AnnotationTarget> injectConstructors = injections.stream().filter(Injection::isConstructor)
                    .map(Injection::getTarget).collect(Collectors.toSet());
            if (injectConstructors.size() > 1) {
                throw new DefinitionException(
                        "Multiple @Inject constructors found on " + beanTarget.asClass().name() + ":\n"
                                + injectConstructors.stream().map(Object::toString).collect(Collectors.joining("\n")));
            }
            for (AnnotationTarget injectConstructor : injectConstructors) {
                Set<AnnotationInstance> parameterAnnotations = Annotations.getParameterAnnotations(beanDeployment,
                        injectConstructor.asMethod());
                for (AnnotationInstance annotation : parameterAnnotations) {
                    if (DotNames.DISPOSES.equals(annotation.name())) {
                        throw new DefinitionException(
                                "Bean constructor must not have a @Disposes parameter: " + injectConstructor);
                    }
                    if (DotNames.OBSERVES.equals(annotation.name())) {
                        throw new DefinitionException(
                                "Bean constructor must not have an @Observes parameter: " + injectConstructor);
                    }
                    if (DotNames.OBSERVES_ASYNC.equals(annotation.name())) {
                        throw new DefinitionException(
                                "Bean constructor must not have an @ObservesAsync parameter: " + injectConstructor);
                    }
                }
            }

            Set<MethodInfo> initializerMethods = injections.stream()
                    .filter(it -> it.isMethod() && !it.isConstructor())
                    .map(Injection::getTarget)
                    .map(AnnotationTarget::asMethod)
                    .collect(Collectors.toSet());

View on GitHub (pinned to e1c734241f)

Solutions

  1. Remove the @Disposes annotation from the bean constructor parameter
  2. Create a proper disposer: a @Produces method in the same class that creates the resource, and a separate @Disposes method taking the produced object
  3. Keep the constructor parameter as a plain injection point if disposal is not actually needed
  4. Rebuild with mvn compile; the failure occurs during Quarkus augmentation so fix source and rebuild

Example fix

// before
@ApplicationScoped
class DbBean {
    DbBean(@Disposes DbConnection conn) { ... }
}

// after
@ApplicationScoped
class DbBean {
    private final DbConnection conn;
    DbBean(DbConnection conn) { this.conn = conn; }

    @Produces
    DbConnection connect() { return open(); }

    void dispose(@Disposes DbConnection conn) { conn.close(); }
}
Defensive patterns

Strategy: validation

Validate before calling

// Build-time augmentation failure: validate annotations before building
void checkConstructor(Method ctor) throws Exception {
    for (var p : ctor.getParameters()) {
        if (p.isAnnotationPresent(jakarta.enterprise.inject.Disposes.class)) {
            throw new IllegalStateException("@Disposes on constructor param: " + ctor);
        }
    }
}

Prevention

When it happens

Trigger: Declaring a @Inject (bean) constructor whose parameter list contains a parameter annotated @jakarta.enterprise.inject.Disposes (or javax variant). ArC collects the constructor's parameter annotations in forBean and fails validation before bean metadata is generated.

Common situations: Copy-pasting a disposer method signature into a constructor; IDE auto-import picking @Disposes when wiring disposal logic; misunderstanding that the container can infer disposal from the constructor; migrating code where a dispose method was merged into a constructor.

Related errors


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