Introduction

Spring Boot application startup failures occur when the ApplicationContext cannot initialize due to bean creation errors, misconfiguration, or external dependency failures. The application fails fast during the startup phase, never reaching a running state. Errors manifest as ApplicationContextException, BeanCreationException, BinderException, or specific cause exceptions like CommunicationsException for database failures. Startup failures are particularly challenging because the application cannot serve health checks or accept traffic, and error messages may be nested several levels deep in the stack trace.

Symptoms

  • Application exits immediately after starting with exit code 1
  • Logs show APPLICATION_FAILED with stack trace
  • BeanCreationException or ApplicationContextException in logs
  • Startup failure after Finished SpringApplication.run
  • Kubernetes pod shows CrashLoopBackOff with application logs showing startup error
  • Issue appears after deploy with configuration changes, dependency updates, or environment changes

Common Causes

  • @Bean method throws exception during initialization
  • Required configuration property missing or invalid type
  • Database connection failed (wrong URL, credentials, or database down)
  • Port already in use (another process or duplicate application)
  • Auto-configuration conflict (multiple implementations on classpath)
  • Circular dependency between beans
  • Classpath issues (missing dependency, version conflict)
  • Profile-specific configuration not activated correctly

Step-by-Step Fix

### 1. Analyze startup failure logs

Extract the root cause from stack trace:

```bash # Spring Boot startup logs show failure analysis # Look for this section:

*************************** APPLICATION FAILED TO START ***************************

Description: An attempt was made to call a method that does not exist. The attempt was made from the following location:

org.springframework.boot.SpringApplication.run(SpringApplication.java:XXX)

Action: Update your dependencies to ensure compatibility

# Or for bean creation failures:

Description: Parameter 0 of constructor in com.example.MyService required a bean of type 'com.example.MyRepository' that could not be found.

Action: Consider defining a bean of type 'com.example.MyRepository' in your configuration. ```

Enable debug logging:

```yaml # application.yml logging: level: root: WARN com.example: DEBUG org.springframework: DEBUG org.springframework.boot.autoconfigure: DEBUG

# Or via environment variable export DEBUG=true java -jar myapp.jar

# Or command line java -jar myapp.jar --debug ```

Analyze condition evaluation report:

```bash # Spring Boot prints condition evaluation report with --debug # Look for:

CONDITIONS EVALUATION REPORT ============================

Positive matches: -----------------

DataSourceAutoConfiguration matched: - @ConditionalOnClass found required classes 'javax.sql.DataSource', 'org.springframework.jdbc.core.JdbcTemplate' (OnClassCondition) - @ConditionalOnProperty spring.datasource.url (OnPropertyCondition)

Negative matches: -----------------

RedisAutoConfiguration did not match: - @ConditionalOnClass did not find required class 'org.springframework.data.redis.RedisConnection' (OnClassCondition)

# This shows which auto-configurations were applied and why others were skipped ```

### 2. Check for port binding conflicts

Port already in use is a common failure:

``` *************************** APPLICATION FAILED TO START ***************************

Description: Web server failed to start. Port 8080 was already in use.

Action: Identify and stop the process currently listening on port 8080 or configure this application to listen on another port. ```

Check port usage:

```bash # Linux/Mac lsof -i :8080 netstat -tlnp | grep 8080 ss -tlnp | grep 8080

# Windows netstat -ano | findstr :8080

# Kill process on port fuser -k 8080/tcp # Linux kill -9 $(lsof -t -i:8080) # Mac/Linux ```

Configure different port:

```yaml # application.yml server: port: 8081 # Use different port

# Or random available port (for tests) server: port: 0 ```

Programmatic port selection:

java @SpringBootApplication public class MyApplication { public static void main(String[] args) { new SpringApplicationBuilder(MyApplication.class) .properties("server.port=8081") .run(args); } }

### 3. Check database connectivity

Database connection failures are common:

``` *************************** APPLICATION FAILED TO START ***************************

Description: Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.

Reason: Failed to determine a suitable driver class ```

Fix DataSource configuration:

yaml # application.yml spring: datasource: url: jdbc:postgresql://localhost:5432/mydb username: ${DB_USERNAME:postgres} password: ${DB_PASSWORD:secret} driver-class-name: org.postgresql.Driver hikari: connection-timeout: 30000 maximum-pool-size: 10

Test connection before Spring starts:

```java @Configuration public class DatabaseHealthCheck {

@Bean public DataSource dataSource(DataSourceProperties properties) { HikariConfig config = new HikariConfig(); config.setJdbcUrl(properties.getUrl()); config.setUsername(properties.getUsername()); config.setPassword(properties.getPassword());

// Test connection during startup try (HikariDataSource ds = new HikariDataSource(config); Connection conn = ds.getConnection()) { // Connection successful System.out.println("Database connection test: OK"); } catch (SQLException e) { throw new BeanCreationException( "Database connection failed: " + e.getMessage(), e); }

return new HikariDataSource(config); } } ```

Check database availability:

```bash # Test database connectivity nc -zv localhost 5432 psql -h localhost -U postgres -d mydb -c "SELECT 1"

# Check if database is accepting connections # MySQL mysql -h localhost -u root -p -e "SELECT 1"

# For remote database telnet db.example.com 5432 ```

### 4. Check configuration property binding

Invalid configuration causes startup failure:

``` *************************** APPLICATION FAILED TO START ***************************

Description: Binding to target com.example.MyProperties@xxxx failed:

Property: myapp.max-connections Value: "not-a-number" Reason: Failed to convert property value of type 'java.lang.String' to required type 'java.lang.Integer' ```

Fix configuration:

yaml # application.yml myapp: max-connections: 100 # Must be integer, not string timeout: 30s # Use Duration format enabled: true # Boolean features: # List - feature1 - feature2

Configuration class:

```java @Configuration @ConfigurationProperties(prefix = "myapp") @Validated public class MyAppProperties {

@NotNull @Min(1) @Max(1000) private Integer maxConnections = 100;

@NotNull private Duration timeout = Duration.ofSeconds(30);

private boolean enabled = true;

private List<String> features = new ArrayList<>();

// Getters and setters } ```

Validate configuration at startup:

```java @Component public class ConfigurationValidator implements ApplicationRunner {

private final MyAppProperties properties;

public ConfigurationValidator(MyAppProperties properties) { this.properties = properties; }

@Override public void run(ApplicationArguments args) { if (properties.getMaxConnections() > 500) { throw new BeanValidationException( "max-connections cannot exceed 500"); } System.out.println("Configuration validated successfully"); } } ```

### 5. Check bean creation and circular dependencies

Circular dependencies prevent bean creation:

``` *************************** APPLICATION FAILED TO START ***************************

Description:

The dependencies of some of the beans in the application context form a cycle:

serviceA defined in class path resource [com/example/ServiceA.class] ┌─────┐ ↓ ↑ serviceB defined in class path resource [com/example/ServiceB.class] ┌─────┐ ↓ ↑ serviceC defined in class path resource [com/example/ServiceC.class] └─────┘ ```

Fix circular dependency:

```java // WRONG: Circular dependency @Service public class ServiceA { private final ServiceB serviceB;

public ServiceA(ServiceB serviceB) { this.serviceB = serviceB; } }

@Service public class ServiceB { private final ServiceA serviceA; // Creates cycle

public ServiceB(ServiceA serviceA) { this.serviceA = serviceA; } }

// CORRECT: Break cycle with interface or @Lazy @Service public class ServiceA { private final ServiceB serviceB;

public ServiceA(ServiceB serviceB) { this.serviceB = serviceB; } }

@Service public class ServiceB { private final ObjectProvider<ServiceA> serviceAProvider; // Lazy injection

public ServiceB(ObjectProvider<ServiceA> serviceAProvider) { this.serviceAProvider = serviceAProvider; }

public void doSomething() { ServiceA serviceA = serviceAProvider.getIfAvailable(); serviceA.doWork(); } } ```

Or use @Lazy:

```java @Service public class ServiceB { private final ServiceA serviceA;

public ServiceB(@Lazy ServiceA serviceA) { this.serviceA = serviceA; } } ```

### 6. Check auto-configuration conflicts

Multiple auto-configurations may conflict:

``` *************************** APPLICATION FAILED TO START ***************************

Description:

The following methods, when combined, create an ambiguous bean definition:

@Bean method MyConfig.dataSource() @Bean method AutoConfig.dataSource() ```

Exclude conflicting auto-configuration:

java @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, RedisAutoConfiguration.class }) public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }

Or via properties:

yaml # application.yml spring: autoconfigure: exclude: - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration - org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration

Define explicit beans:

```java @Configuration public class MyConfig {

@Bean @Primary // Mark as primary if multiple exist public DataSource dataSource() { HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:postgresql://localhost:5432/mydb"); return new HikariDataSource(config); } } ```

### 7. Check classpath and dependency conflicts

Missing or conflicting dependencies:

``` *************************** APPLICATION FAILED TO START ***************************

Description:

An attempt was made to call a method that does not exist. The attempt was made from the following location:

com.example.MyService.init(MyService.java:42)

The following method did not exist:

'void com.google.common.collect.ImmutableList.of(java.lang.Object)'

The method's class, com.google.common.collect.ImmutableList, is available from the following locations:

jar:file:/.../guava-20.0.jar!/com/google/common/collect/ImmutableList.class

The method's class version (52.0) is older than the required version (55.0). ```

Fix dependency conflicts:

```xml <!-- pom.xml --> <dependencies> <!-- Force specific version --> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>32.0.0-jre</version> </dependency>

<!-- Exclude transitive dependency --> <dependency> <groupId>org.example</groupId> <artifactId>some-lib</artifactId> <exclusions> <exclusion> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </exclusion> </exclusions> </dependency> </dependencies>

<!-- Use dependency management --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>3.2.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> ```

Check for dependency conflicts:

```bash # Maven: show dependency tree mvn dependency:tree

# Find conflicting versions mvn dependency:tree -Dverbose -Dincludes=com.google.guava

# Gradle: show dependencies ./gradlew dependencies

# Find duplicate classes mvn org.apache.maven.plugins:maven-enforcer-plugin:enforce -Drules=requireUpperBoundDeps ```

### 8. Check profile-specific configuration

Wrong profile activation causes failures:

```bash # Check active profiles java -jar myapp.jar --spring.profiles.active=dev

# Or via environment export SPRING_PROFILES_ACTIVE=dev java -jar myapp.jar

# Or in application.yml spring: profiles: active: dev ```

Profile-specific configuration:

```yaml # application.yml (common) spring: datasource: url: ${DB_URL}

# application-dev.yml spring: datasource: url: jdbc:postgresql://localhost:5432/devdb username: dev password: dev

# application-prod.yml spring: datasource: url: jdbc:postgresql://prod-db:5432/proddb username: ${PROD_DB_USER} password: ${PROD_DB_PASS} ```

Validate profile at startup:

```java @Component @Profile("dev") public class DevProfileChecker implements ApplicationRunner {

@Override public void run(ApplicationArguments args) { System.out.println("Running with 'dev' profile"); // Dev-specific initialization } } ```

### 9. Implement graceful startup failure handling

Custom failure analyzer:

```java public class DatabaseConnectionFailureAnalyzer implements FailureAnalyzer {

@Override public FailureAnalysis analyze(Throwable rootFailure) { if (rootFailure instanceof CannotCreateTransactionException) { Throwable cause = rootFailure.getCause(); if (cause instanceof SQLException) { return new FailureAnalysis( "Database connection failed", "Check database URL, credentials, and network connectivity", cause); } } return null; // Let other analyzers handle } } ```

Register analyzer:

# META-INF/spring.factories org.springframework.boot.diagnostics.FailureAnalyzer=\ com.example.DatabaseConnectionFailureAnalyzer

Startup health check:

```java @Component public class StartupHealthChecker implements ApplicationRunner {

private final List<HealthChecker> checkers;

public StartupHealthChecker(List<HealthChecker> checkers) { this.checkers = checkers; }

@Override public void run(ApplicationArguments args) { for (HealthChecker checker : checkers) { try { checker.check(); System.out.println(checker.name() + ": OK"); } catch (Exception e) { System.err.println(checker.name() + ": FAILED - " + e.getMessage()); throw new BeanCreationException( "Startup health check failed: " + checker.name(), e); } } } }

interface HealthChecker { String name(); void check() throws Exception; } ```

### 10. Enable startup failure analysis

Spring Boot's failure analysis provides actionable messages:

```java // Custom exception with failure analysis public class ConfigurationException extends RuntimeException {

private final String action;

public ConfigurationException(String description, String action) { super(description); this.action = action; }

public String getAction() { return action; } }

// Throw with actionable message throw new ConfigurationException( "Database URL not configured", "Set SPRING_DATASOURCE_URL environment variable or add 'spring.datasource.url' to application.yml" ); ```

Prevention

  • Use @ConfigurationProperties with validation for type-safe configuration
  • Implement startup health checks for all external dependencies
  • Use Spring Boot Actuator for startup diagnostics
  • Enable debug logging in development environments
  • Test configuration changes in staging before production
  • Use profile-specific configuration files consistently
  • Document required environment variables and configuration
  • **ApplicationContextException**: Parent exception for context failures
  • **BeanCreationException**: Specific bean failed to create
  • **BinderException**: Configuration property binding failed
  • **PortInUseException**: Server port already bound