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
- Remove the @Disposes annotation from the bean constructor parameter
- Create a proper disposer: a @Produces method in the same class that creates the resource, and a separate @Disposes method taking the produced object
- Keep the constructor parameter as a plain injection point if disposal is not actually needed
- 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
- Never put lifecycle annotations (@Disposes, @Observes, @ObservesAsync) on constructor parameters
- Pair every @Produces method with a separate @Disposes method in the same class
- Run ./mvnw compile frequently so augmentation errors surface immediately
- Use a CDI spec linter or IDE CDI support to flag illegal annotations early
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
- Initializer method must not have a @Disposes parameter (alte
- Producer method must not have a @Disposes parameter (alterna
- Bean constructor must not have an @Observes parameter:
- Bean constructor must not have an @ObservesAsync parameter:
- Initializer method must not be annotated @Produces (alternat
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/72ce2c30eaf1e15b.
Report an issue: GitHub.