SpringBoot
BeanDefinitionOverrideException
Spring Framework
Java
Exception Handling

SpringBoot - BeanDefinitionOverrideException Invalid bean definition

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

BeanDefinitionOverrideException happens when Spring finds multiple bean definitions with the same name while overriding is disabled. This error is a safety feature that prevents accidental replacement of configuration. The best fix is resolving naming and wiring intent, not blindly enabling global override.

Why the Exception Happens

Common causes:

  • Two @Bean methods with same method name.
  • Two components explicitly named the same.
  • Test configuration colliding with application bean names.
  • Custom beans colliding with auto-configuration names.

Example collision:

java
1@Configuration
2public class PrimaryConfig {
3    @Bean
4    public MyService myService() {
5        return new MyServiceImplA();
6    }
7}
8
9@Configuration
10public class SecondaryConfig {
11    @Bean
12    public MyService myService() {
13        return new MyServiceImplB();
14    }
15}

Both definitions map to bean name myService.

Fix with Explicit Names and Qualifiers

Give implementations distinct names and inject by qualifier.

java
1@Configuration
2public class ServiceConfig {
3
4    @Bean("myServiceA")
5    public MyService myServiceA() {
6        return new MyServiceImplA();
7    }
8
9    @Bean("myServiceB")
10    public MyService myServiceB() {
11        return new MyServiceImplB();
12    }
13}

Injection:

java
1import org.springframework.beans.factory.annotation.Qualifier;
2import org.springframework.stereotype.Service;
3
4@Service
5public class BillingService {
6    private final MyService myService;
7
8    public BillingService(@Qualifier("myServiceA") MyService myService) {
9        this.myService = myService;
10    }
11}

This makes dependency intent explicit and reviewable.

@Primary Is Not a Name-Collision Fix

@Primary helps when multiple beans of same type exist for autowiring by type. It does not resolve duplicate bean name registration.

Use @Primary only after bean names are distinct and valid.

Control Scan Boundaries

Overly broad scanning can pull in unintended classes and create collisions.

java
@SpringBootApplication(scanBasePackages = "com.example.app")
public class App {
}

In tests, isolate @TestConfiguration and avoid loading full app context unless required.

Should You Enable Bean Override

Spring allows override via property:

properties
spring.main.allow-bean-definition-overriding=true

Use this only when replacement is deliberate and documented. As a default policy, it can hide configuration bugs and create surprising environment-specific behavior.

Prefer Conditional Beans for Environment Differences

When different implementations are needed per profile or property, use conditional registration.

java
1@Bean
2@ConditionalOnProperty(name = "feature.mock-service", havingValue = "true")
3public MyService mockService() {
4    return new MyServiceImplB();
5}

Conditional wiring communicates intent better than silent overriding.

Debugging Workflow

When exception occurs:

  1. Read the two conflicting bean definitions in startup message.
  2. Search codebase for the duplicated bean name.
  3. Check imported test configs and auto-config classes.
  4. Rename or scope beans explicitly.

Enable startup debug report for more context:

properties
debug=true

This often reveals auto-configuration sources involved in collisions.

Preventive Practices

  • Use descriptive bean method names.
  • Avoid generic names reused across modules.
  • Keep architecture tests for duplicate naming patterns.
  • Review new config classes for overlap with existing modules.

Preventing collisions in reviews is cheaper than startup-failure triage later.

Another useful safeguard is module-level naming conventions. For example, prefix infrastructure beans with infra and feature beans with bounded-context names. This lowers collision probability as codebase size grows and makes startup diagnostics easier to interpret when conflicts still occur. If your team uses shared starter modules, publish a documented list of exported bean names. This avoids accidental collisions when application modules define similarly named custom beans. This registry also improves architectural visibility during large refactoring efforts.

Common Pitfalls

  • Enabling global override as first reaction.
  • Assuming @Primary resolves same-name registrations.
  • Reusing generic bean names across unrelated configs.
  • Mixing test and production config in one scanned package.
  • Ignoring auto-config bean names when defining custom replacements.

Summary

  • The exception signals duplicate bean names with override protection active.
  • Resolve conflicts with explicit names and qualifier-based injection.
  • Use @Primary only for type preference, not name collision fixes.
  • Prefer conditional registration over global override settings.
  • Keep scan scope and config boundaries intentional to avoid future collisions.

Course illustration
Course illustration

All Rights Reserved.