No Qualifying Bean of Type Available: How to Fix It in Spring Boot
-
Last Updated: November 4, 2026
-
By: javahandson
-
Series

The “No qualifying bean of type” error stops your Spring Boot app at startup, and it confuses almost every developer the first time. In plain words, Spring wanted to inject a bean, but it could not find a matching one. Sometimes it finds none. Other times it finds too many. This guide walks through the exact message, why it happens, a tiny example you can reproduce, and the fixes in priority order. At the end, you will see how to confirm the fix actually worked.
You usually spot one of these messages in the startup log. The first one appears when Spring finds no matching bean at all:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.app.PaymentService' available: expected at least 1 bean which qualifies as autowire candidate
The second one appears when Spring finds more than one candidate and cannot choose:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.example.app.PaymentService' available: expected single matching bean but found 2: cardPaymentService,upiPaymentService
Spring Boot also prints a friendlier version through its failure analyzer:
Description: Field paymentService in com.example.app.OrderController required a bean of type 'com.example.app.PaymentService' that could not be found. Action: Consider defining a bean of type 'com.example.app.PaymentService' in your configuration.
All three point to the same root problem. The dependency injection container could not give your class the bean it asked for.
Spring builds your application as a graph of beans. When one class needs another, Spring injects it from the container. First, it tries to match by type. If a name is given, it matches by name as well.
This error shows up when that match fails. Interestingly, there are only two ways it can fail.
Spring looked for a bean of the required type and found none. The class may well exist in your code. However, Spring never registered it as a bean, so the container has nothing to hand over.
Here Spring found two or more beans of the same type. Now it cannot decide which one you meant. This throws NoUniqueBeanDefinitionException, which belongs to the same exception family. The message reads “expected single matching bean but found 2”.
Keep both flavours in mind. The fix you pick depends entirely on which one you are facing.
Let us create the error on purpose. Take an interface, an injection point, but no stereotype annotation on the implementation:
public interface PaymentService {
void pay(long amount);
}
// Notice: no @Service, @Component or @Repository here
public class CardPaymentService implements PaymentService {
public void pay(long amount) {
System.out.println("Paid " + amount);
}
}
@RestController
public class OrderController {
private final PaymentService paymentService;
public OrderController(PaymentService paymentService) {
this.paymentService = paymentService;
}
}Run this app and it fails at startup. CardPaymentService is just a plain class, not a Spring bean. Therefore Spring has no PaymentService to inject, and the “No qualifying bean of type” error shows up.
Work through these from top to bottom. The first two solve the large majority of cases.
This is the most common cause by far. Your implementation class needs a stereotype annotation so that Spring registers it as a bean.
@Service
public class CardPaymentService implements PaymentService {
public void pay(long amount) { /* ... */ }
}Use the right annotation for the role:
@Service — business logic and service classes@Repository — data access classes (it also translates database exceptions)@Component — anything generic that does not fit the others@RestController or @Controller — web layer classesOne frequent slip is annotating the interface instead of the class. Always put the annotation on the concrete class, because Spring creates beans from classes, not interfaces.
Even with @Service in place, Spring only finds the class if it sits inside a scanned package. By default, @SpringBootApplication scans its own package and everything below it.
Picture this layout:
com.example.app -> Application.java (@SpringBootApplication) com.example.service -> CardPaymentService.java (scanned, good) org.other.payments -> RefundService.java (NOT scanned, fails)
Any class outside the main package tree stays invisible to scanning. Luckily, you have two clean options:
@SpringBootApplication(scanBasePackages = {"com.example", "org.other"})
public class Application { /* ... */ }Try not to scatter @ComponentScan everywhere. One deliberate base package stays much easier to maintain.
This tackles Flavour 2, the NoUniqueBeanDefinitionException. Say you have two payment services:
@Service
public class CardPaymentService implements PaymentService { /* ... */ }
@Service
public class UpiPaymentService implements PaymentService { /* ... */ }Now Spring has two candidates and cannot pick one for you. So you tell it which to use.
Option A — mark a default with @Primary:
@Service
@Primary
public class CardPaymentService implements PaymentService { /* ... */ }Spring now injects CardPaymentService wherever the type is PaymentService, unless you ask otherwise.
Option B — select by name with @Qualifier:
@RestController
public class OrderController {
private final PaymentService paymentService;
public OrderController(
@Qualifier("upiPaymentService") PaymentService paymentService) {
this.paymentService = paymentService;
}
}@Qualifier is more precise, because it names the exact bean. As a rule, use @Primary for the common default, and @Qualifier at the few spots that need the other bean.
Sometimes the class you need lives inside a library. You cannot add @Service to code you do not own. In that case, declare the bean yourself inside a @Configuration class:
@Configuration
public class AppConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}The method return type becomes the bean type. As a result, RestTemplate can now be injected anywhere. This also works for your own classes when you prefer explicit configuration over scanning.
Your app may run fine, yet a test fails with the same error. That happens because test slice annotations load only part of the context on purpose.
@WebMvcTest loads controllers, not services or repositories.@DataJpaTest loads repositories, not your services.So a bean that exists in production is simply absent in the slice. Two fixes help here.
First, provide the missing bean with @MockBean (or @MockitoBean on newer Spring):
@WebMvcTest(OrderController.class)
class OrderControllerTest {
@MockBean
PaymentService paymentService;
}Alternatively, switch to @SpringBootTest when you genuinely need the full context. Match the test type to what the test actually needs. A slice keeps tests fast, though you must supply its missing collaborators.
Do not just assume it works. Instead, confirm it with a quick check.
Start the app again. A clean startup with no NoSuchBeanDefinitionException is your first green signal. The failure analyzer block disappears once the bean resolves.
Add Actuator and expose the beans endpoint:
management.endpoints.web.exposure.include=beans
Then open http://localhost:8080/actuator/beans and search for your type. If the bean shows up in the list, Spring registered it correctly.
A small test proves the bean is wired without running the whole app:
@SpringBootTest
class BeanWiringTest {
@Autowired
PaymentService paymentService;
@Test
void paymentServiceLoads() {
assertThat(paymentService).isNotNull();
}
}If the context loads and the field is not null, your dependency injection is healthy again.
Run through this list whenever the error comes back:
@Service, @Component or @Repository?@Bean method?@Primary or @Qualifier.@MockBean or switch to @SpringBootTest.Nine times out of ten, the answer is a missing annotation or a package sitting outside the scan.