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

  1. Mark exactly one candidate @Primary so the type-resolved injection has a single winner.
  2. Add @Qualifier('beanName') on the injection point (field, constructor param, setter) to select a candidate.
  3. Reduce the candidates: remove one of the bean definitions, or guard them with @Profile so only one is active.
  4. Inject a List<T>/Map<String,T>/ObjectProvider<T> when you genuinely want all candidates.
  5. 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

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


AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09). Data as JSON: /api/errors/bc3ce91cb0d18b4e. Report an issue: GitHub.