'Invalid bean definition' when migrating Spring Boot 2.0.6 to 2.1.0 with EvaluationContextExtensionSupport and custom PermissionEvaluator
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
A migration from Spring Boot 2.0.x to 2.1.x can surface bean-registration errors that never appeared before. One common reason is that Spring Boot 2.1 disables bean definition overriding by default. If your security setup exposes custom beans through EvaluationContextExtensionSupport, a custom PermissionEvaluator, or both, a duplicate bean name that used to be silently overridden can now fail application startup.
What Changed In Spring Boot 2.1
Before Spring Boot 2.1, two beans with the same name could be registered and the later one would often replace the earlier one. In Spring Boot 2.1, bean overriding is disabled by default, so duplicate bean names now cause startup failure instead of being silently accepted.
That means an upgrade can break code that was already ambiguous.
This matters in security configuration because custom evaluators and evaluation-context extensions are often declared with framework-adjacent names such as permissionEvaluator or similar helper bean names.
A Typical Duplicate-Bean Scenario
Suppose you have a custom permission evaluator and a configuration class that also exposes related beans.
If another configuration, auto-configuration path, or imported module also registers a bean with the same name, Boot 2.1 can fail with an invalid bean definition or bean override exception instead of allowing one to replace the other.
The problem is usually not EvaluationContextExtensionSupport itself. It is the collision that becomes visible during migration.
Exposing Custom Security Expressions Safely
A typical extension based on EvaluationContextExtensionSupport looks like this.
This is fine as long as the beans involved are uniquely named and intentionally wired.
Preferred Fixes
The best fix is usually to remove the ambiguity rather than simply re-enable bean overriding.
Practical options are:
- rename one of the conflicting beans
- inject by type with
@Primaryonly when multiple beans are intentionally present - isolate your security extension in one configuration path so it is registered exactly once
Example with explicit bean names:
This makes the wiring intent clearer and avoids silent name collisions.
Compatibility Fallback
If you need a short-term migration bridge, you can re-enable the old override behavior.
That may get the application running, but it should be treated as a compatibility fallback, not the ideal final state. Silent overriding can hide configuration mistakes that are better fixed explicitly.
Common Pitfalls
A common mistake is assuming the upgrade broke PermissionEvaluator or EvaluationContextExtensionSupport directly. In many cases the real issue is duplicate bean registration becoming visible.
Another mistake is solving the problem only by enabling bean overriding. That restores old behavior, but it also restores the ambiguity that caused the surprise.
Developers also often focus on injection by type while the actual failure is bean naming. Boot 2.1 made name collisions much less forgiving.
Finally, when multiple security configuration classes are imported conditionally, verify that they are not both creating the same bean under different migration paths.
Summary
- Spring Boot 2.1 disables bean definition overriding by default.
- Migrations can therefore expose duplicate bean names that used to be silently overridden.
- Custom
PermissionEvaluatorandEvaluationContextExtensionSupportsetups are common places where this appears. - Prefer unique bean names and explicit wiring over silent override behavior.
- '
spring.main.allow-bean-definition-overriding=trueis a short-term compatibility fallback, not usually the best long-term fix.' - Treat the migration error as a signal to clean up ambiguous configuration.

