quarkusio/quarkus · error · DefinitionException
Multiple disposer methods found for producer '${producer}' d
Error message
Multiple disposer methods found for producer '${producer}' declared on ${declaringBean}:
- ${disposerMethod} What it means
CDI allows at most one disposer method per producer. If two or more disposer methods resolve to the same producer (matching the produced type and qualifiers) within the same bean class, ArC throws this DefinitionException listing all offending disposer methods.
Source
Thrown at independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java:1558
}
if (hasQualifier) {
Type disposedParamType = disposer.getDisposedParameterType();
for (Type beanType : beanTypes) {
if (beanResolver.matches(disposedParamType, beanType)) {
found.add(disposer);
break;
}
}
}
}
}
if (found.size() > 1) {
StringBuilder error = new StringBuilder("Multiple disposer methods found for producer '")
.append(producer).append("' declared on ").append(declaringBean).append(":\n");
for (DisposerInfo disposer : found) {
error.append("\t- ").append(disposer.getDisposerMethod()).append("\n");
}
throw new DefinitionException(error.toString());
}
return found.isEmpty() ? null : found.get(0);
}
// keep it public we need this method in quarkus integration
public static Set<DotName> initBeanDefiningAnnotations(Collection<BeanDefiningAnnotation> additionalBeanDefiningAnnotations,
Set<DotName> stereotypes) {
Set<DotName> beanDefiningAnnotations = new HashSet<>();
for (BuiltinScope scope : BuiltinScope.values()) {
beanDefiningAnnotations.add(scope.getInfo().getDotName());
}
if (additionalBeanDefiningAnnotations != null) {
for (BeanDefiningAnnotation additional : additionalBeanDefiningAnnotations) {
beanDefiningAnnotations.add(additional.getAnnotation());
}
}
beanDefiningAnnotations.addAll(stereotypes);
return beanDefiningAnnotations;View on GitHub (pinned to e1c734241f)
Solutions
- Delete one of the duplicate disposer methods, consolidating cleanup logic into the remaining one.
- If both cleanups are needed, call both operations from a single disposer method.
- Rename qualifiers/types so each disposer matches a distinct producer.
Example fix
// before
class Cfg {
@Produces Conn connect() { ... }
@Disposes void closeA(Conn c) { c.close(); }
@Disposes void closeB(Conn c) { c.release(); }
}
// after
class Cfg {
@Produces Conn connect() { ... }
@Disposes void close(Conn c) { c.release(); c.close(); }
} Defensive patterns
Strategy: validation
Validate before calling
// At build time: count disposer methods per bean class
long disposers = Arrays.stream(cls.getDeclaredMethods())
.filter(m -> Arrays.stream(m.getParameterAnnotations())
.flatMap(Stream::of).anyMatch(a -> a instanceof Disposes.class)).count();
if (disposers > 1) {
throw new IllegalStateException("More than one disposer in " + cls);
} Prevention
- One disposer per bean class; consolidate cleanup there
- Refactor multi-step cleanup into a single disposer body
- Watch for inherited producers plus subclass disposers
When it happens
Trigger: Two @Disposes methods in a bean class both accept parameters assignable to the same producer's type/qualifiers — typically duplicates created by inheritance or copy-paste of a close()/cleanup() method.
Common situations: Copy-pasting a disposer to handle cleanup differently; subclass adding a disposer for an inherited producer; merging branches that each added a disposer for the same producer.
Related errors
- No producer method or field declared by the bean class that
- No disposed parameters found for ${disposerMethod}
- Unsupported injection point target: <injectionPoint>
- Method ${method} of class ${beanClass} is not a producer met
- Injected field cannot be annotated with @Produces: ${field}
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/6f683d20d0b394ce.
Report an issue: GitHub.