quarkusio/quarkus · error · AmbiguousResolutionException
Beans: " + resolvedBeans
Error message
Beans: " + resolvedBeans
What it means
Arc throws AmbiguousResolutionException when bean resolution for a required type/qualifier set matches more than one bean. CDI requires exactly one bean to resolve an injection point; the message lists all resolved beans so you can see the conflict. This enforces the CDI 'unresolvable ambiguous dependency' rule at injection time.
Source
Thrown at independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/ArcContainerImpl.java:328
@Override
public <X> InstanceHandle<X> instance(Type type, Annotation... qualifiers) {
return instanceHandle(type, qualifiers);
}
@Override
public <T> Supplier<InstanceHandle<T>> beanInstanceSupplier(Class<T> type, Annotation... qualifiers) {
if (qualifiers == null || qualifiers.length == 0) {
qualifiers = new Annotation[] { Default.Literal.INSTANCE };
}
Resolvable resolvable = new Resolvable(type, qualifiers);
Set<InjectableBean<?>> resolvedBeans = resolved.getValue(resolvable);
if (resolvedBeans.isEmpty()) {
scanRemovedBeans(resolvable);
}
Set<InjectableBean<?>> filteredBean = resolvedBeans;
if (resolvedBeans.size() > 1) {
throw new AmbiguousResolutionException("Beans: " + resolvedBeans);
}
@SuppressWarnings("unchecked")
InjectableBean<T> bean = filteredBean.size() != 1 ? null
: (InjectableBean<T>) filteredBean.iterator().next();
if (bean == null) {
return null;
}
InjectionPoint injectionPoint = InjectionPointImpl.of(type, qualifiers);
return new Supplier<InstanceHandle<T>>() {
@Override
public InstanceHandle<T> get() {
return beanInstanceHandle(bean, null, injectionPoint, null);
}
};
}
@OverrideView on GitHub (pinned to e1c734241f)
Solutions
- Add a distinguishing qualifier (@Named, custom @Qualifier) to the injection point or to one of the beans
- Mark all but one of the conflicting beans @Alternative and enable exactly one in application.properties (quarkus.arc.selected-alternatives)
- Use programmatic lookup: inject Instance<MyType> and call .select(qualifier).get()
- Use @Priority or @Vetoed / remove the unwanted bean from discovery
Example fix
// before @Inject GreetingService service; // two implementations -> ambiguous // after @Inject @English GreetingService service; // qualifier disambiguates
Defensive patterns
Strategy: validation
Validate before calling
Set<Bean<?>> beans = Arc.container().getBeans(MyType.class);
if (beans.size() > 1) {
throw new IllegalStateException("Ambiguous beans for MyType: " + beans);
} Try / catch
try {
service = instance.select(qualifier).get();
} catch (AmbiguousResolutionException e) {
LOGGER.errorf("Ambiguous beans: %s", e.getMessage());
service = instance.select(qualifier, AdditionalQualifiers...).get();
} Prevention
- Give every multi-implementation interface a dedicated @Qualifier
- Audit beans exposing the same interface after adding dependencies
- Prefer Instance<T> programmatic lookup when multiple implementations may exist
- Enable exactly one @Alternative and verify with quarkus.arc.selected-alternatives
When it happens
Trigger: Calling Instance.get()/beanInstanceSupplier resolution where two or more beans (e.g. two @Alternative-less implementations, or a producer and a class bean) share the required type and qualifiers. Also occurs at container init for programmatic lookup of a type satisfied by multiple beans.
Common situations: Adding a second implementation of an interface without @Alternative/@Named/@Unique qualifier; a library bean and an application bean both exposing the same API; upgrading a dependency that now registers an extra bean; forgetting to enable only one @Alternative.
Related errors
- Beans:
- No matching bean in CDI context for type ${instance}
- Bean not found for localized interface [{e.value}] and local
- Multiple beans found for localized interface [{e.value}] and
- No current injection point found
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/a2bdb3a3b32203d1.
Report an issue: GitHub.