quarkusio/quarkus · error · AmbiguousResolutionException
Beans:
Error message
Beans:
What it means
When Instance resolution finds more than one bean matching the required type and qualifiers, ArC throws AmbiguousResolutionException('Beans: ' + list). The message enumerates the ambiguous beans so you can see exactly which candidates conflict.
Source
Thrown at independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/InstanceImpl.java:291
if (resetCurrentInjectionPoint) {
InjectionPointProvider.setCurrent(context, prev);
}
}
}
},
// If @Dependent we need to remove the instance from the CC of this InjectableInstance
Dependent.class.equals(bean.getScope()) ? this::destroy : null);
}
@SuppressWarnings("unchecked")
private InjectableBean<T> bean() {
List<InjectableBean<?>> beans = beans();
if (beans.isEmpty()) {
ArcContainerImpl.instance().scanRemovedBeans(requiredType, requiredQualifiers.toArray(new Annotation[] {}));
throw new UnsatisfiedResolutionException(
"No bean found for required type [" + requiredType + "] and qualifiers [" + requiredQualifiers + "]");
} else if (beans.size() > 1) {
throw new AmbiguousResolutionException("Beans: " + beans.toString());
}
return (InjectableBean<T>) beans.iterator().next();
}
public boolean hasDependentInstances() {
return creationalContext.hasDependentInstances();
}
@Override
public void clearCache() {
if (cachedGetResult.isSet()) {
creationalContext.release();
cachedGetResult.clear();
}
}
private T getInternal() {
return getBeanInstance(bean());View on GitHub (pinned to e1c734241f)
Solutions
- Add a distinguishing qualifier annotation to each implementation and select with it
- Mark one implementation @Alternative (and activate it in application.properties) or @Default/@Priority
- Narrow the select() call with additional qualifiers so only one bean matches
- If one bean should never be used, make it @Vetoed or remove it
Example fix
// before
instance.select(PaymentService.class).get(); // 2 impls -> ambiguous
// after
@Qualifier @Retention(RUNTIME) @interface Stripe {}
instance.select(PaymentService.class, new Stripe.Literal()).get(); Defensive patterns
Strategy: validation
Validate before calling
Instance<PaymentService> candidates = instance.select(PaymentService.class, qualifier);
if (candidates.isAmbiguous()) {
throw new IllegalStateException("Multiple beans for PaymentService: add a qualifier or @Alternative");
} Type guard
static <T> T unique(Instance<T> i) {
if (i.isAmbiguous()) throw new IllegalStateException("Ambiguous: " + i.stream().map(b -> b.getBean().getBeanClass()).toList());
if (i.isUnsatisfied()) throw new IllegalStateException("Unsatisfied");
return i.get();
} Try / catch
try {
svc = instance.select(PaymentService.class).get();
} catch (AmbiguousResolutionException e) {
log.errorf("Ambiguous beans: %s — add qualifier/Alternative", e.getMessage());
throw e;
} Prevention
- Give every multi-implementation interface a qualifier per implementation
- Run a startup smoke test — ambiguous resolution fails fast at first lookup
- Use @Default and @Alternative deliberately; audit them when adding new implementations
- Check Instance.isAmbiguous() before get()
When it happens
Trigger: Calling instance.get()/getHandle() after select() where two or more beans match the type and qualifiers — e.g. two implementations of the same interface with the same/default qualifiers.
Common situations: Adding a second implementation of an interface used elsewhere with default qualifiers; a library upgrade introduces a bean that duplicates an app bean; forgotten @Alternative/@Default differentiation.
Related errors
- No active bean found
- Beans: " + resolvedBeans
- Cannot obtain InjectionPoint metadata for non-@Dependent bea
- No bean found for required type [
- Quarkus does not support CDI Full @Specializes annotation; t
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/d8c6671358817d54.
Report an issue: GitHub.