spring-projects/spring-security · error · NoUniqueBeanDefinitionException
Expected single matching bean of type…
Error message
Expected single matching bean of type 'org.springframework.security.oauth2.client.OAuth2AuthorizedClientService' but found {}: {} What it means
During OAuth2 client configuration, getAuthorizedClientServiceBean queries the ApplicationContext for OAuth2AuthorizedClientService beans. This IllegalStateException fires when the lookup does not return exactly one bean (zero found, or more than one candidate), leaving the builder unable to determine which authorized-client service to use. Configuration is ambiguous or missing, so startup fails rather than guessing.
Solutions
- Register exactly one OAuth2AuthorizedClientService bean (e.g. a JdbcOAuth2AuthorizedClientService) or mark one @Primary
- Remove duplicate OAuth2AuthorizedClientService definitions from the context
- Omit the bean entirely to accept the default InMemoryOAuth2AuthorizedClientService backed by getClientRegistrationRepository
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurerUtils.java:108 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/d80c95e7c0178fc4.
Report an issue: GitHub.
Appendix: source
Thrown at config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurerUtils.java:108
}
private static <B extends HttpSecurityBuilder<B>> OAuth2AuthorizedClientService getAuthorizedClientService(
B builder) {
OAuth2AuthorizedClientService authorizedClientService = getAuthorizedClientServiceBean(builder);
if (authorizedClientService == null) {
authorizedClientService = new InMemoryOAuth2AuthorizedClientService(
getClientRegistrationRepository(builder));
}
return authorizedClientService;
}
private static <B extends HttpSecurityBuilder<B>> OAuth2AuthorizedClientService getAuthorizedClientServiceBean(
B builder) {
Map<String, OAuth2AuthorizedClientService> authorizedClientServiceMap = BeanFactoryUtils
.beansOfTypeIncludingAncestors(builder.getSharedObject(ApplicationContext.class),
OAuth2AuthorizedClientService.class);
if (authorizedClientServiceMap.size() > 1) {
throw new NoUniqueBeanDefinitionException(OAuth2AuthorizedClientService.class,
authorizedClientServiceMap.size(),
"Expected single matching bean of type '" + OAuth2AuthorizedClientService.class.getName()
+ "' but found " + authorizedClientServiceMap.size() + ": "
+ StringUtils.collectionToCommaDelimitedString(authorizedClientServiceMap.keySet()));
}
return (!authorizedClientServiceMap.isEmpty() ? authorizedClientServiceMap.values().iterator().next() : null);
}
static <B extends HttpSecurityBuilder<B>> OidcSessionRegistry getOidcSessionRegistry(B builder) {
OidcSessionRegistry sessionRegistry = builder.getSharedObject(OidcSessionRegistry.class);
if (sessionRegistry != null) {
return sessionRegistry;
}
ApplicationContext context = builder.getSharedObject(ApplicationContext.class);
if (context.getBeanNamesForType(OidcSessionRegistry.class).length == 1) {
sessionRegistry = context.getBean(OidcSessionRegistry.class);
}
else {View on GitHub (pinned to 96852e8860)