LEARN · DEBUGGING GUIDE

Spring Boot Auto-configuration Not Loading: Debugging Conditional Beans

If Spring Boot auto-configuration isn't loading, it's almost always a conditional evaluation failure. This guide shows you exactly how to trace which condition blocked the bean and why.

IntermediateJava6 min read

What this usually means

Spring Boot auto-configuration relies on a set of @Conditional annotations (e.g., @ConditionalOnClass, @ConditionalOnProperty, @ConditionalOnBean) to decide whether to load a bean. When a condition fails, the entire auto-configuration class is skipped—no beans from that class are created. The most common reason is a missing or incompatible dependency on the classpath, a missing property, or the bean that the condition depends on not being present. The debug logs and the auto-configuration report are your best friends here.

( 01 )Fast diagnosis

The first ten minutes — establish facts before touching code.

  • 1Set logging level: add 'logging.level.org.springframework.boot.autoconfigure=DEBUG' to application.properties
  • 2Check the auto-configuration report: add '--debug' to the command line or set 'debug=true', then look for 'Positive matches' and 'Negative matches'
  • 3Search for the missing class: grep the class name in your dependency tree with 'mvn dependency:tree' or 'gradle dependencies'
  • 4Verify property presence: check if the required property is set and correctly spelled in your application.yml or .properties file
  • 5Enable condition evaluation report by adding 'spring.autoconfigure.exclude' or by checking the autoconfigure log
  • 6Inspect the @ConditionalOnClass annotation: the class FQN must match exactly, and the class must be available at runtime
  • 7Check for component scan conflicts: ensure the auto-configuration class itself is not excluded by @ComponentScan filters
( 02 )Where to look

The specific files, logs, configs, and dashboards that usually own this bug.

  • searchApplication logs with DEBUG level for org.springframework.boot.autoconfigure
  • searchAuto-configuration report generated with '--debug' flag (console output)
  • searchspring.factories file under META-INF/spring/ (for auto-configuration imports)
  • searchMaven/Gradle dependency tree to verify transitive dependencies
  • search@ConditionalOnClass, @ConditionalOnProperty, @ConditionalOnBean annotations on the auto-configuration class
  • searchapplication.properties / application.yml for property-based conditions
  • searchClasspath scan logs: look for 'Skipped auto-configuration class' entries
( 03 )Common root causes

Practical causes, not theory. These are the things you will actually find.

  • warningMissing optional dependency: a library is declared as 'optional' in Maven or 'compileOnly' in Gradle and not included at runtime
  • warningTypo in @ConditionalOnProperty value: property name or havingValue does not match exactly
  • warningClass not on classpath due to version conflict: a transitive dependency excludes the required class
  • warningAuto-configuration class excluded explicitly via @EnableAutoConfiguration(exclude=...) or spring.autoconfigure.exclude
  • warningBean required by @ConditionalOnBean is not created because its own condition failed
  • warningWrong class name or package in @ConditionalOnClass: typo in the fully qualified class name
  • warningConditionalOnMissingBean overrides: a user-defined bean of the same type prevents auto-configuration
( 04 )Fix patterns

Concrete fix directions. Pick the one that matches your root cause.

  • buildAdd the missing dependency explicitly: for Maven, add the artifact with compile scope; for Gradle, use implementation instead of compileOnly
  • buildCorrect property names: ensure @ConditionalOnProperty(name="...", havingValue="...") matches exactly what is in application.properties
  • buildUse @ConditionalOnMissingBean to allow user overrides, but document that auto-configuration will not load if a custom bean exists
  • buildRemove auto-configuration exclusions: check if spring.autoconfigure.exclude contains the class and remove it
  • buildAlign dependency versions: use the Spring Boot BOM to ensure consistent versions
  • buildFor ConditionalOnClass, add the missing JAR to the classpath or replace with a different condition if the library is optional
  • buildCreate a custom auto-configuration that manually checks conditions and logs a clear message when skipped
( 05 )How to verify

A fix you cannot prove is a guess. Close the loop.

  • verifiedRestart the application with DEBUG logging and confirm the auto-configuration appears under 'Positive matches'
  • verifiedWrite a simple test that @Autowired the expected bean and assert it is not null
  • verifiedCheck the condition evaluation report: the expected condition should show 'matched: true'
  • verifiedVerify that the class from @ConditionalOnClass is loadable: use Class.forName() in a test or check the classpath
  • verifiedSet a breakpoint in the auto-configuration class constructor or @PostConstruct to confirm execution
  • verifiedUse Spring Boot Actuator's /actuator/conditions endpoint (if enabled) to see live condition matches
( 06 )Mistakes to avoid

Things that make this bug worse or harder to find.

  • warningRelying on default logging levels: always set logging.level.org.springframework.boot.autoconfigure=DEBUG explicitly
  • warningAssuming auto-configuration loads just because the library is on the classpath—check each @Conditional annotation
  • warningForgetting that @ConditionalOnMissingBean means auto-configuration will NOT load if a user-defined bean exists
  • warningUsing @ConditionalOnClass with a class that is only available in a different profile/scope
  • warningOverlooking transitive dependency exclusions that remove a required JAR
  • warningNot checking the spring.factories file: if auto-configuration is not listed, it won't be discovered
( 07 )War story

The Phantom Redis Connection: Why LettuceConnectionFactory Was Never Created

Senior Backend EngineerSpring Boot 2.7, Redis, Lettuce, Maven, Java 11

Timeline

  1. 09:15Deploy new microservice to staging; health check fails with 'Redis connection refused'.
  2. 09:20Check application logs: no error, but RedisTemplate bean is null in a @Service.
  3. 09:25Add 'logging.level.org.springframework.boot.autoconfigure=DEBUG' and restart.
  4. 09:28Logs show 'Negative match: RedisAutoConfiguration matched: false'.
  5. 09:32Check condition details: 'ConditionalOnClass: LettuceConnectionProvider failed'.
  6. 09:35Run 'mvn dependency:tree' - no Lettuce JAR found.
  7. 09:38Inspect pom.xml: spring-boot-starter-data-redis is declared but with <scope>provided</scope> (copy-paste error).
  8. 09:42Change scope to 'compile', rebuild, redeploy.
  9. 09:45Health check passes; RedisTemplate bean is available.

I was deploying a new microservice that needed Redis caching. The application started fine—no errors—but our health check endpoint kept failing with 'Redis connection refused'. That was weird because we hadn't even configured a Redis connection yet; it was supposed to auto-configure from the cloud environment.

I opened the logs and saw nothing out of the ordinary. Then I remembered: Spring Boot auto-configuration often fails silently. I added DEBUG logging for autoconfigure and restarted. The log showed 'Negative match: RedisAutoConfiguration'. I dug into the condition report: 'ConditionalOnClass: LettuceConnectionProvider' failed. That meant Lettuce wasn't on the classpath.

I checked the pom.xml and found spring-boot-starter-data-redis with scope 'provided'. Someone had copy-pasted a dependency from a servlet project. I changed it to 'compile', rebuilt, and redeployed. The health check passed. The fix was trivial, but the silent failure cost us an hour of debugging because I didn't check the auto-configuration report first.

Root cause

Spring Boot's Redis auto-configuration requires LettuceConnectionProvider on the classpath (from @ConditionalOnClass). The dependency spring-boot-starter-data-redis was declared with 'provided' scope, so Lettuce was not available at runtime.

The fix

Changed the Maven scope of spring-boot-starter-data-redis from 'provided' to 'compile'.

The lesson

Always enable DEBUG logging for autoconfigure when a bean is missing silently. The condition evaluation report pinpoints exactly which condition failed and why.

( 08 )Reading the Condition Evaluation Report

The auto-configuration report is the single most useful tool for debugging. To generate it, run your application with --debug or set debug=true in application.properties. The output contains two sections: 'Positive matches' (auto-configurations that loaded) and 'Negative matches' (those that didn't, with reasons).

Each negative match shows the class name and the condition that failed. For example: 'RedisAutoConfiguration matched: false - @ConditionalOnClass did not find required class 'org.springframework.data.redis.connection.lettuce.LettuceConnectionProvider'.' This tells you exactly which jar is missing. Use this to guide your dependency investigation.

( 09 )Common Conditional Annotations and Their Pitfalls

@ConditionalOnClass: checks that one or more classes are present. Pitfall: you must use the fully qualified class name (FQN). A typo or wrong package will fail. Also, the class must be loadable, not just present in the dependency graph—if the jar is on the classpath but the class has a different version, it might fail.

@ConditionalOnProperty: checks that a property exists with a specific value. Pitfall: property names are case-sensitive, and the havingValue must be an exact string match. Also, if the property is not set at all, the condition defaults to false unless matchIfMissing = true.

@ConditionalOnBean: checks that a bean of a certain type already exists. Pitfall: if the bean depends on another auto-configuration that also fails, this condition will fail. Circular conditions can be tricky.

( 10 )Using Spring Boot Actuator for Live Condition Inspection

If your application is running and you want to inspect conditions without restarting, enable the conditions endpoint: add spring-boot-starter-actuator and set management.endpoints.web.exposure.include=conditions. Then hit GET /actuator/conditions.

The response is a JSON object with two keys: 'positiveMatches' and 'negativeMatches'. Each entry contains the condition class and its outcome. This is especially useful in production where you cannot restart with debug flags.

( 11 )Debugging Auto-configuration Exclusions

Sometimes auto-configuration is explicitly excluded via @EnableAutoConfiguration(exclude=...) or spring.autoconfigure.exclude. If you can't find the class in the negative matches of the condition report, check if it's excluded. The logs will show 'Excluding auto-configuration class' at DEBUG level.

Also check if the auto-configuration class is listed in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports (for Spring Boot 2.7+) or spring.factories (older versions). If it's missing, auto-configuration won't be discovered at all.

Frequently asked questions

Why does my auto-configuration not load even though the condition shows 'matched: true'?

If the condition matches but the bean still isn't created, check if the auto-configuration class itself is excluded. Also, verify that the bean is not overridden by a user-defined @Bean with the same type and name (if @ConditionalOnMissingBean is used). Finally, ensure that the auto-configuration class is not filtered out by @ComponentScan excludeFilters.

How do I see all auto-configuration conditions without restarting the application?

Use Spring Boot Actuator's /actuator/conditions endpoint. Enable it by adding the actuator dependency and setting 'management.endpoints.web.exposure.include=conditions'. Then you can GET that endpoint to see positive and negative matches live.

What's the difference between @ConditionalOnClass and @ConditionalOnBean?

@ConditionalOnClass checks if a class (or multiple classes) are present on the classpath—it's about compile-time dependencies. @ConditionalOnBean checks if a Spring bean of a certain type already exists in the context—it's about runtime bean availability. The former is evaluated before the application context is fully loaded; the latter is evaluated during bean registration.

Can a missing optional dependency cause auto-configuration to not load?

Yes. If a dependency is declared as 'optional' in Maven or 'compileOnly' in Gradle, it is NOT included in the transitive dependency tree of projects that depend on your project. Therefore, @ConditionalOnClass will fail at runtime. To fix, either make the dependency non-optional or add it explicitly to the consuming project.

How do I debug auto-configuration when using Spring Cloud or other starters?

The same principles apply. Enable DEBUG logging for org.springframework.boot.autoconfigure and look for negative matches. Spring Cloud starters often have their own auto-configurations with additional conditions (e.g., @ConditionalOnCloudPlatform). Check the Spring Cloud documentation for specific conditions.