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.
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
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
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
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
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
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
The Phantom Redis Connection: Why LettuceConnectionFactory Was Never Created
Timeline
- 09:15Deploy new microservice to staging; health check fails with 'Redis connection refused'.
- 09:20Check application logs: no error, but RedisTemplate bean is null in a @Service.
- 09:25Add 'logging.level.org.springframework.boot.autoconfigure=DEBUG' and restart.
- 09:28Logs show 'Negative match: RedisAutoConfiguration matched: false'.
- 09:32Check condition details: 'ConditionalOnClass: LettuceConnectionProvider failed'.
- 09:35Run 'mvn dependency:tree' - no Lettuce JAR found.
- 09:38Inspect pom.xml: spring-boot-starter-data-redis is declared but with <scope>provided</scope> (copy-paste error).
- 09:42Change scope to 'compile', rebuild, redeploy.
- 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.
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.
@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.
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.
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.