apache/dubbo · error · ScopeBeanException
expected single matching bean but found ${size} candidates f
Error message
expected single matching bean but found ${size} candidates for type [${type}]: ${candidateBeanNames} What it means
Thrown by ScopeBeanFactory.getBeanInternal when resolving by type only (or with a name that does not exactly match) and more than one registered bean is assignable to the requested type. Dubbo cannot guess which instance to return, so it lists the candidate bean names and aborts. This mirrors Spring's NoUniqueBeanDefinitionException.
Source
Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/beans/factory/ScopeBeanFactory.java:348
} else {
if (candidates == null) {
candidates = new ArrayList<>();
candidates.add(firstCandidate);
}
candidates.add(beanInfo);
}
}
}
}
// if bean name not matched and only single candidate
if (candidates != null) {
if (candidates.size() == 1) {
return (T) candidates.get(0).instance;
} else if (candidates.size() > 1) {
List<String> candidateBeanNames =
candidates.stream().map(beanInfo -> beanInfo.name).collect(Collectors.toList());
throw new ScopeBeanException("expected single matching bean but found " + candidates.size()
+ " candidates for type [" + type.getName() + "]: " + candidateBeanNames);
}
} else if (firstCandidate != null) {
return (T) firstCandidate.instance;
}
return null;
}
public void destroy() {
if (destroyed.compareAndSet(false, true)) {
for (BeanInfo beanInfo : registeredBeanInfos) {
if (beanInfo.instance instanceof Disposable) {
try {
Disposable beanInstance = (Disposable) beanInfo.instance;
beanInstance.destroy();
} catch (Throwable e) {
LOGGER.error(
CONFIG_FAILED_DESTROY_INVOKER,View on GitHub (pinned to 3a3043227f)
Solutions
- Request the bean by the exact name of one of the candidates listed in the message.
- Make the bean name match when registering, so getBean(name, type) resolves uniquely.
- Reduce to a single bean of that type in the scope, or mark one as primary/removable for your use case.
- If you need all instances, use an injection point for a List<T> / iterate registered beans instead of getBean.
Example fix
// before
factory.registerBean("a", MyImpl.class);
factory.registerBean("b", MyImpl.class);
MyApi bean = factory.getBean(MyApi.class); // ambiguous -> error
// after
MyApi bean = factory.getBean("a", MyApi.class); // exact name match Defensive patterns
Strategy: validation
Validate before calling
// Count assignable candidates before resolving by type
<T> long candidateCount(ScopeBeanFactory f, Class<T> type) {
// public getBean throws on ambiguity; instead detect by attempting exact names
long n = 0;
for (String name : knownNames) {
if (f.getBean(name, type) != null) n++;
}
return n;
} Try / catch
try {
T bean = factory.getBean(type);
} catch (ScopeBeanException e) {
if (e.getMessage().startsWith("expected single matching bean")) {
// parse candidate names from the message and pick one explicitly:
// bean = factory.getBean(candidateName, type);
} else throw e;
} Prevention
- Resolve beans by exact name when multiple implementations of a type exist.
- Keep one primary bean per type within a scope, or use qualifiers/names consistently.
- If you need all instances of a type, iterate registered beans instead of getBean(type).
- When registering multiple same-type beans, document and use their names.
When it happens
Trigger: Calling getBean(type) or getBean(name, type) where name does not equal any registered bean's name, and two or more beans assignable to type exist. Common when multiple implementations of an interface/SPI are registered in the same scope.
Common situations: Multiple @DubboService implementations of the same interface; two beans of compatible types registered by different modules sharing a ScopeBeanFactory; custom extensions that register duplicate-type beans; requesting an interface bean without a qualifier.
Related errors
- already exists bean with same name and type, name=${name}, t
- unable to determine bean class from factory's superclass or
- create bean instance failed, type=${className}
- register bean failed! name=${name}, type=${className}
- ScopeBeanFactory is destroyed
AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14).
Data as JSON: /api/errors/8b644584db561847.
Report an issue: GitHub.