Fix: Spring Boot Failed to Configure DataSource (DataSource Auto-Configuration Error)
Part of: Database Errors
Quick Answer
How to fix Spring Boot 'Failed to configure a DataSource' errors — missing URL property, driver class not found, connection refused, and how to correctly configure datasource properties for MySQL, PostgreSQL, and H2.
The Error
Spring Boot fails to start with:
***************************
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 classOr with a specific driver error:
Unable to determine Tomcat connection pool library.
java.lang.RuntimeException: Driver com.mysql.cj.jdbc.Driver claims to not accept jdbcUrlOr a connection error at startup:
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:
Communications link failure — Last packet sent to the server was 0 ms ago.Or:
org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException:
Failed to determine a suitable driver classWhy This Happens
Spring Boot auto-configures a DataSource when it finds a database driver on the classpath. The auto-configuration requires at minimum a spring.datasource.url property. The auto-configuration is opt-out by design — adding spring-boot-starter-data-jpa or spring-boot-starter-jdbc triggers it even if you never wrote a @Configuration class for a DataSource.
The error message you see is usually the wrapper. The real cause is one layer deeper in the stack trace. Spring’s DataSourceAutoConfiguration walks through a chain: detect driver on classpath, resolve properties, pick a connection pool, validate the URL, attempt the first connection. Each step has a distinct failure mode, and the surface error reads the same.
Common root causes:
spring.datasource.urlis missing or empty — the most common cause. Spring Boot cannot guess the database URL and refuses to fall back to an embedded H2 when a real driver is on the classpath.- Database driver not on the classpath — the JDBC driver dependency is missing from
pom.xmlorbuild.gradle, or scoped asprovidedwhen it should beruntime. - Wrong JDBC URL format — the URL does not match the driver’s expected format. PostgreSQL wants
jdbc:postgresql://, MySQL wantsjdbc:mysql://, Oracle wantsjdbc:oracle:thin:@. - Database server is not running or not reachable — connection refused at startup. Common in Docker Compose when the app starts before the database is healthy.
- Wrong credentials — the username/password in properties does not match the database user, or the secret was not injected into the container.
- Spring Data JPA on classpath without a database configured — adding
spring-boot-starter-data-jpatriggers DataSource auto-configuration. If you do not need a database, exclude it. - Profile-specific properties not loaded —
application-prod.ymlwas not packaged into the jar, orSPRING_PROFILES_ACTIVEwas not set in the deployment environment.
Fix 1: Add the Required datasource Properties
The minimum required configuration:
# src/main/resources/application.properties
# PostgreSQL
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.datasource.username=myuser
spring.datasource.password=mypassword
spring.datasource.driver-class-name=org.postgresql.Driver
# MySQL
spring.datasource.url=jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC
spring.datasource.username=myuser
spring.datasource.password=mypassword
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# H2 in-memory (for development/testing)
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.h2.console.enabled=trueYAML format:
# src/main/resources/application.yml
spring:
datasource:
url: jdbc:postgresql://localhost:5432/mydb
username: myuser
password: mypassword
driver-class-name: org.postgresql.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialectNote:
driver-class-nameis optional when the JDBC URL prefix matches a known driver on the classpath. Spring Boot infers the driver fromjdbc:postgresql://→ PostgreSQL driver,jdbc:mysql://→ MySQL driver, etc. Specify it explicitly if auto-detection fails.
Fix 2: Add the JDBC Driver Dependency
If the driver is not on the classpath, Spring Boot cannot connect regardless of properties.
Maven — add to pom.xml:
<!-- PostgreSQL -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- H2 (in-memory, for tests) -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>Gradle — add to build.gradle:
dependencies {
// PostgreSQL
runtimeOnly 'org.postgresql:postgresql'
// MySQL
runtimeOnly 'com.mysql:mysql-connector-j'
// H2 (tests only)
testRuntimeOnly 'com.h2database:h2'
}After adding the dependency, run:
# Maven
mvn clean install
# Gradle
./gradlew dependencies | grep -i postgresqlFix 3: Fix JDBC URL Format
Each database requires a specific URL format:
PostgreSQL:
# Standard
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
# With SSL
spring.datasource.url=jdbc:postgresql://host:5432/mydb?sslmode=require
# Cloud SQL (GCP)
spring.datasource.url=jdbc:postgresql:///mydb?cloudSqlInstance=project:region:instance&socketFactory=com.google.cloud.sql.postgres.SocketFactoryMySQL:
# MySQL 8.x — use CJ driver
spring.datasource.url=jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
# Common parameters to add when you see connection errors:
# useSSL=false — disable SSL for local dev
# serverTimezone=UTC — required by MySQL Connector/J 8.0+
# allowPublicKeyRetrieval=true — required for some MySQL 8 auth configurationsSQL Server:
spring.datasource.url=jdbc:sqlserver://localhost:1433;databaseName=mydb;encrypt=false
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriverH2 (file-based instead of in-memory):
spring.datasource.url=jdbc:h2:file:./data/mydb;AUTO_SERVER=TRUEFix 4: Use Environment Variables for Credentials
Hardcoding credentials in application.properties is a security risk. Use environment variables or a secrets manager:
# application.properties — references environment variables
spring.datasource.url=${DATABASE_URL}
spring.datasource.username=${DATABASE_USERNAME}
spring.datasource.password=${DATABASE_PASSWORD}# Set environment variables before running
export DATABASE_URL=jdbc:postgresql://localhost:5432/mydb
export DATABASE_USERNAME=myuser
export DATABASE_PASSWORD=secret
java -jar app.jarSpring Boot also reads from .env via system properties at runtime:
java -DDATABASE_URL=jdbc:postgresql://localhost:5432/mydb -jar app.jarFor different environments — use Spring profiles:
# application.properties (defaults)
spring.profiles.active=dev
# application-dev.properties
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
# application-prod.properties
spring.datasource.url=${DATABASE_URL}
spring.datasource.username=${DATABASE_USERNAME}
spring.datasource.password=${DATABASE_PASSWORD}# Activate a profile at runtime
java -Dspring.profiles.active=prod -jar app.jar
# Or:
SPRING_PROFILES_ACTIVE=prod java -jar app.jarFix 5: Exclude DataSource Auto-Configuration When Not Needed
If you added spring-boot-starter-data-jpa or spring-boot-starter-jdbc but do not actually need a database (e.g., you use MongoDB only), exclude the DataSource auto-configuration:
// Main application class
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class
})
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}Or via properties:
spring.autoconfigure.exclude=\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfigurationFix 6: Fix Connection Pool Configuration
Spring Boot uses HikariCP by default. Connection pool exhaustion causes startup failures or slow queries at runtime:
# HikariCP connection pool settings
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.connection-timeout=30000 # 30 seconds
spring.datasource.hikari.idle-timeout=600000 # 10 minutes
spring.datasource.hikari.max-lifetime=1800000 # 30 minutes
spring.datasource.hikari.connection-test-query=SELECT 1
# For PostgreSQL — use pgBouncer URL with transaction mode
# spring.datasource.hikari.connection-init-sql=SET search_path TO myschemaDiagnose pool exhaustion:
# Enable HikariCP logging
logging.level.com.zaxxer.hikari=DEBUG
logging.level.com.zaxxer.hikari.HikariConfig=DEBUGFix 7: Test the Connection Outside Spring Boot
If Spring Boot cannot connect, verify the connection parameters are correct first:
# Test PostgreSQL connection with psql
psql -h localhost -p 5432 -U myuser -d mydb
# Test MySQL connection
mysql -h localhost -P 3306 -u myuser -pmypassword mydb
# Test if the port is reachable
nc -zv localhost 5432
telnet localhost 5432Simple Java connection test (without Spring):
import java.sql.Connection;
import java.sql.DriverManager;
public class TestConnection {
public static void main(String[] args) throws Exception {
String url = "jdbc:postgresql://localhost:5432/mydb";
String user = "myuser";
String password = "mypassword";
try (Connection conn = DriverManager.getConnection(url, user, password)) {
System.out.println("Connected: " + conn.getMetaData().getDatabaseProductName());
}
}
}In Production: Incident Lens
This is a startup-failure incident, not a runtime degradation. The blast radius is 100 percent of new pods or instances rolling out — they never reach Ready state, so no traffic is served from the new revision. If you are mid-deploy and the old revision is still healthy, the old pods keep serving until they get terminated. If you are doing a blue/green or canary deploy, the canary pods fail their startup probe and the rollout stalls. If you are doing a rolling deploy without proper readiness gating, you can drain old healthy pods before the new ones come up — that is when the outage becomes user-visible.
Detection signals to wire up:
- Spring Boot Actuator
/actuator/healthreturning DOWN with componentdb(Hikari reports pool status here) - Kubernetes
startupProbefailures incrementing on the new pod - Container restart count climbing without ever reaching Ready
- Log pattern
APPLICATION FAILED TO STARTmatched in your log aggregator - Metrics:
hikaricp_connections_activeflat at zero after pod start
Recovery playbook:
- Stop the rollout —
kubectl rollout pause deployment/<name>or pause the pipeline. Do not let more pods cycle through the failure. - Roll back to last known good —
kubectl rollout undo deployment/<name>restores the previous ReplicaSet. This buys you time. - Diff the configuration — compare the failing revision’s ConfigMap / env vars / Secret against the previous one. The bad value is almost always in
SPRING_DATASOURCE_URL,SPRING_DATASOURCE_USERNAME, orSPRING_DATASOURCE_PASSWORD. - Verify the secret was actually injected —
kubectl execinto a fresh debug pod with the same service account and print the env. Missing env is a very common root cause when secrets are sourced from external systems. - Test connectivity from the pod network —
nc -zv db-host 5432. If this fails, the issue is networking or DNS, not Spring.
Prevention:
- Move credentials into HashiCorp Vault, AWS Secrets Manager, or GCP Secret Manager. Inject via the platform’s secret-mount mechanism so rotation does not require a redeploy.
- Make Kubernetes
readinessProbehit/actuator/health/readinessso pods do not receive traffic until the DataSource is actually live. - Gate deploys on a smoke test that hits a
/healthzendpoint that exercises a real query (not just a pool ping). - Add a contract test that boots the application context against a Testcontainers Postgres in CI — this catches missing properties before they reach production.
Still Not Working?
Check the full stack trace. The Failed to configure a DataSource message is often a wrapper — the root cause is further down:
Caused by: java.net.ConnectException: Connection refused
at java.net.PlainSocketImpl.socketConnect(Native Method)Connection refused means the database server is not running or not listening on the expected port. Check:
# PostgreSQL
sudo systemctl status postgresql
sudo -u postgres psql -c '\l'
# MySQL
sudo systemctl status mysql
mysql -u root -pCheck if the database exists. Spring Boot connects to a specific database — if the database does not exist, the connection fails even if the server is running:
-- PostgreSQL
CREATE DATABASE mydb;
GRANT ALL PRIVILEGES ON DATABASE mydb TO myuser;
-- MySQL
CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
GRANT ALL PRIVILEGES ON mydb.* TO 'myuser'@'localhost';
FLUSH PRIVILEGES;Check Flyway or Liquibase migration failures. If you use database migration tools, a failed migration prevents Spring Boot from starting. Check the migration logs and the flyway_schema_history table for failed entries. A migration that ran partially and then crashed leaves the schema in a state where the next attempt cannot proceed — repair with mvn flyway:repair or by manually clearing the bad row.
Check for SSL handshake failures. Managed databases (RDS, Cloud SQL, Azure Database) often require SSL by default. If your URL omits sslmode=require or your CA bundle is missing, you get SSLException: PKIX path building failed wrapped inside the DataSource error. Add the cloud provider’s certificate to the JVM trust store, or set sslmode=require plus sslrootcert=... in the URL.
Check for IPv4 vs IPv6 binding mismatches. A database listening on 127.0.0.1 only is unreachable from a container that resolves localhost to ::1. Either bind the database to 0.0.0.0 (carefully — only for dev) or use the explicit IPv4 address in the JDBC URL.
Check the Hikari pool initialization order. When spring.datasource.hikari.initialization-fail-timeout is set to its default of 1ms, Hikari attempts a connection at startup and fails the context if the database is not immediately reachable. Setting it to -1 makes Hikari lazy (fail at first use instead of startup) — sometimes appropriate for batch jobs but rarely for web services.
For related Spring Boot and Java database issues, see Fix: Spring Boot WhiteLabel Error Page, Fix: MySQL Access Denied for User, Fix: PostgreSQL Connection Refused, and Fix: Spring Data JPA Query Not Working.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: Spring Data JPA Query Not Working — @Query, Derived Methods, and N+1 Problems
How to fix Spring Data JPA query issues — JPQL vs native SQL, derived method naming, @Modifying for updates, pagination, projections, and LazyInitializationException.
Fix: Spring Boot @Transactional Not Rolling Back — Transaction Committed Despite Exception
How to fix Spring @Transactional not rolling back — checked vs unchecked exceptions, self-invocation proxy bypass, rollbackFor, transaction propagation, and nested transactions.
Fix: Spring Boot Failed to Configure a DataSource
How to fix 'Failed to configure a DataSource: url attribute is not specified' in Spring Boot — adding database properties, excluding DataSource auto-configuration, H2 vs production DB setup, and multi-datasource configuration.
Fix: Spring Boot @Cacheable Not Working — Cache Miss Every Time or Stale Data
How to fix Spring Boot @Cacheable issues — @EnableCaching missing, self-invocation bypass, key generation, TTL configuration, cache eviction, and Caffeine vs Redis setup.