No Qualifying Bean of Type Available: How to Fix It in Spring Boot

  • Last Updated: November 4, 2026
  • By: javahandson
  • Series
img

No Qualifying Bean of Type Available: How to Fix It in Spring Boot

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.

1. What the error looks like

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.

2. Why Spring throws “No qualifying bean of type”

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.

Flavour 1: zero beans match

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.

Flavour 2: too many beans match

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.

3. A minimal example that reproduces it

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.

4. How to fix it (in priority order)

Work through these from top to bottom. The first two solve the large majority of cases.

Fix 1: add the missing stereotype annotation

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 classes

One 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.

Fix 2: check component scanning and package layout

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:

  • Move the class under your main application package. This is the simplest fix.
  • Or widen the scan explicitly:
@SpringBootApplication(scanBasePackages = {"com.example", "org.other"})
public class Application { /* ... */ }

Try not to scatter @ComponentScan everywhere. One deliberate base package stays much easier to maintain.

Fix 3: resolve multiple implementations

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.

Fix 4: register third-party beans with @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.

Fix 5: watch out for test slices

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.

5. How to verify the fix

Do not just assume it works. Instead, confirm it with a quick check.

Restart and read the startup log

Start the app again. A clean startup with no NoSuchBeanDefinitionException is your first green signal. The failure analyzer block disappears once the bean resolves.

List the beans through Actuator

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.

Write a tiny context test

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.

6. Quick checklist

Run through this list whenever the error comes back:

  • Does the implementation class have @Service, @Component or @Repository?
  • Is the annotation on the class, not on the interface?
  • Is the class inside your scanned package tree?
  • For library classes, did you add a @Bean method?
  • Two implementations? Add @Primary or @Qualifier.
  • Failing only in tests? Add @MockBean or switch to @SpringBootTest.

Nine times out of ten, the answer is a missing annotation or a package sitting outside the scan.

Further reading

Leave a Comment