spring-projects/spring-framework · error · NoUniqueBeanDefinitionException
No unique bean definition
Error message
No unique bean definition
What it means
Thrown as a NoUniqueBeanDefinitionException by DependencyDescriptor.resolveNotUnique when multiple beans of the requested type survive qualifier filtering and none is marked @Primary, no @Qualifier pins one down, and the injection is not a collection/Optional. It is the default resolution for the not-unique scenario, designed to be overridden by subclasses that want to pick a winner or opt out.
Source
Thrown at spring-beans/src/main/java/org/springframework/beans/factory/config/DependencyDescriptor.java:192
public boolean isEager() {
return this.eager;
}
/**
* Resolve the specified not-unique scenario: by default,
* throwing a {@link NoUniqueBeanDefinitionException}.
* <p>Subclasses may override this to select one of the instances or
* to opt out with no result at all through returning {@code null}.
* @param type the requested bean type
* @param matchingBeans a map of bean names and corresponding bean
* instances which have been pre-selected for the given type
* (qualifiers etc already applied)
* @return a bean instance to proceed with, or {@code null} for none
* @throws BeansException in case of the not-unique scenario being fatal
* @since 5.1
*/
public @Nullable Object resolveNotUnique(ResolvableType type, Map<String, Object> matchingBeans) throws BeansException {
throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
}
/**
* Resolve a shortcut for this dependency against the given factory, for example
* taking some pre-resolved information into account.
* <p>The resolution algorithm will first attempt to resolve a shortcut through this
* method before going into the regular type matching algorithm across all beans.
* Subclasses may override this method to improve resolution performance based on
* pre-cached information while still receiving {@link InjectionPoint} exposure etc.
* @param beanFactory the associated factory
* @return the shortcut result if any, or {@code null} if none
* @throws BeansException if the shortcut could not be obtained
* @since 4.3.1
*/
public @Nullable Object resolveShortcut(BeanFactory beanFactory) throws BeansException {
return null;
}
View on GitHub (pinned to 69bf83ad71)
Solutions
- Mark exactly one candidate @Primary so the type-resolved injection has a single winner.
- Add @Qualifier('beanName') on the injection point (field, constructor param, setter) to select a candidate.
- Reduce the candidates: remove one of the bean definitions, or guard them with @Profile so only one is active.
- Inject a List<T>/Map<String,T>/ObjectProvider<T> when you genuinely want all candidates.
- If you wrote a custom DependencyDescriptor, override resolveNotUnique to pick a candidate or return null instead of throwing.
Example fix
// before: two DataSource beans, ambiguous autowiring
@Bean DataSource primary() { ... }
@Bean DataSource replica() { ... }
@Autowired DataSource ds; // NoUniqueBeanDefinitionException
// after: disambiguate with @Primary
@Bean @Primary DataSource primary() { ... }
@Bean DataSource replica() { ... } Defensive patterns
Strategy: validation
Validate before calling
String[] names = beanFactory.getBeanNamesForType(requiredType);
if (names.length > 1 && beanFactory.getBean(names[0], requiredType) /* no primary */) {
throw new NoUniqueBeanDefinitionException(requiredType, java.util.Arrays.asList(names));
} Type guard
// True when exactly one candidate is resolvable for the type boolean unique = beanFactory.getBeanNamesForType(type).length == 1;
Try / catch
try {
return beanFactory.getBean(type);
} catch (NoUniqueBeanDefinitionException ex) {
// pick by qualifier, @Primary, or fall back to a default
return beanFactory.getBean(qualifier, type);
} Prevention
- Mark a single candidate @Primary when multiple of a type exist.
- Add @Qualifier on injection points to disambiguate.
- Use @Profile to ensure only one candidate is active per environment.
- Inject List<T>/ObjectProvider<T> when all candidates are genuinely wanted.
When it happens
Trigger: DependencyDescriptor.resolveNotUnique is called by the resolver when more than one candidate bean matches the dependency type (after qualifiers). The default implementation throws NoUniqueBeanDefinitionException with the candidate bean names; subclasses (e.g. ShortcutDependencyDescriptor, parameterized-collection descriptors) override it to choose differently.
Common situations: Two DataSource/RestTemplate/EntityManager beans with no @Primary; multiple @Configuration classes each defining a bean of the same type; autowiring by type where a profile brings in extra candidates; forgotten @Qualifier on an injection point; previously-unique bean now duplicated after adding a starter.
Related errors
- No qualifying bean of type '{}' available: expected single m
- Unsatisfied dependency expressed through field
- Unsatisfied dependency expressed through parameter
- Invalid autowire-marked constructors: {}. Found constructor
- Injection of autowired dependencies failed
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/bc3ce91cb0d18b4e.
Report an issue: GitHub.