Ch. 8 · Spring Boot

Spring Boot: Failed to Configure a DataSource ('url' Not Specified)

Fix 'Failed to configure a DataSource: url attribute is not specified' in Spring Boot 3 by setting the URL, adding the driver or a profile.

~7 min readbeginnerupdated Oct 4, 2026

You added a dependency, pressed run, and Spring Boot stopped before Tomcat even started. On Spring Boot 3.x the console shows this block:

***************************
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


Action:

Consider the following:
	If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
	If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).
Text

It means auto-configuration decided this application needs a DataSource, then could not build one: no spring.datasource.url was found in any active property source, and no embedded database driver was on the classpath to fall back on. Nothing is wrong with your database server. Spring never tried to connect to it.

Quick fix checklist

  • Add spring.datasource.url, username and password to application.properties or application.yml in src/main/resources.
  • Make sure the JDBC driver (for example org.postgresql:postgresql) is a runtime dependency.
  • If your settings live in application-dev.yml, activate the profile: spring.profiles.active=dev or --spring.profiles.active=dev.
  • Check the Action: text: “no profiles are currently active” is a strong hint.
  • For tests or prototypes, add H2 so Boot can create an embedded database.
  • Only if the app truly has no database, remove the JDBC/JPA starter or exclude DataSourceAutoConfiguration.

Before you start

You need a Spring Boot 3.x project (Java 17+) built with Maven or Gradle, and you should know where src/main/resources lives. It helps to know which starter pulled in JDBC: spring-boot-starter-data-jpa, spring-boot-starter-jdbc and spring-boot-starter-data-jdbc all bring spring-jdbc and the HikariCP pool. Code in this article is written for Spring Boot 3.x.

Why it happens

Spring Boot’s auto-configuration reacts to what is on the classpath. DataSourceAutoConfiguration is guarded by @ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class }), so the moment spring-jdbc arrives (directly or through the JPA starter) Boot assumes you want a connection pool.

From there it takes one of two paths:

  1. Pooled DataSource. If a pool such as HikariCP is present, Boot binds spring.datasource.* into DataSourceProperties and builds the pool. To do that it must know the JDBC URL and the driver class. When the URL is missing, it tries to infer an embedded database instead.
  2. Embedded DataSource. If H2, HSQLDB or Derby is on the classpath, Boot can create an in-memory database with a generated URL and no credentials.

When neither path works, DataSourceProperties throws DataSourceBeanCreationException, and a FailureAnalyzer turns that stack trace into the friendly Description: and Action: text. The analyzer also checks the environment: it prints the active profiles, or “no profiles are currently active”, because a forgotten profile is the most common reason a URL that exists in a file was never read.

The Reason: Failed to determine a suitable driver class line is a consequence, not a separate problem. Boot derives the driver from the URL prefix (jdbc:postgresql: means the PostgreSQL driver). No URL, no driver.

Step-by-step walkthrough

Step 1: Reproduce with a minimal project

Create a project with only spring-boot-starter-web and spring-boot-starter-data-jpa, no driver and an empty application.properties. Run it. You get the exact failure above. This proves the cause is configuration, not code: no repository or entity is needed to trigger it, because the decision happens while auto-configuration is evaluated.

Step 2: Read the Description and Action sections

The Description: names the missing piece ('url' attribute). The Action: lists two remedies and the profile state. If it says (the profiles "dev" are currently active) and you still fail, the URL is not in application-dev.* either. If it says no profiles are active, look for a profile-specific file you assumed was loaded.

To see why auto-configuration matched, start with --debug (or debug=true in properties). The condition evaluation report lists DataSourceAutoConfiguration under “Positive matches” with the class conditions it found.

Step 3: Provide the connection settings

For a real database, set the URL and credentials and add the driver:

spring.datasource.url=jdbc:postgresql://localhost:5432/orders
spring.datasource.username=orders_app
spring.datasource.password=${DB_PASSWORD}
spring.jpa.hibernate.ddl-auto=validate
properties

The same in YAML:

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/orders
    username: orders_app
    password: ${DB_PASSWORD}
  jpa:
    hibernate:
      ddl-auto: validate
yaml
<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <scope>runtime</scope>
</dependency>
xml

You rarely need spring.datasource.driver-class-name; Boot infers it from the URL. Set it only for drivers Boot does not recognise.

Gotcha

In YAML, indentation is the structure. datasource: indented under the wrong key, or a tab character, silently produces a different property name such as spring.jpa.datasource.url, and you get the same failure even though the URL is “in the file”.

Step 4: Fix profile and file location problems

If the settings are in application-dev.yml, nothing reads them until dev is active. Choose one way to activate it:

./mvnw spring-boot:run -Dspring-boot.run.profiles=dev
java -jar target/orders.jar --spring.profiles.active=dev
SPRING_PROFILES_ACTIVE=dev ./gradlew bootRun
Terminal

Also confirm the file is in src/main/resources (not src/main/java or the project root) and is named exactly application.properties or application.yml. An IDE run configuration can carry its own active profiles, so check it too.

Step 5: Decide whether you need a DataSource at all

If the service genuinely has no database (a gateway, a batch client calling HTTP APIs), the clean fix is to remove the starter that pulled in JDBC. If a shared library forces spring-jdbc onto your classpath and you cannot remove it, exclude the auto-configuration:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

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

If JPA is also present you will then hit missing EntityManagerFactory errors, which is a sign you do need a database after all.

Worked scenario

A team keeps local settings in application-local.yml so that developers can point at Docker Postgres, and production settings come from environment variables. A new developer clones the repository and runs OrdersApplication from the IDE.

Broken setup:

# src/main/resources/application-local.yml
spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/orders
    username: orders
    password: orders
yaml

application.yml contains only server.port: 8081. The failure output ends with “no profiles are currently active”. That single line is the diagnosis: the URL exists, but in a file Boot never loaded because local was not active.

The tempting fix is to copy the datasource block into application.yml. That works locally and then quietly points every other environment at localhost unless they override it. A better fix is to make activation explicit for local runs and keep the base file free of environment-specific URLs:

# src/main/resources/application.yml
server:
  port: 8081
spring:
  datasource:
    url: ${DATABASE_URL:}
yaml

The developer then runs with SPRING_PROFILES_ACTIVE=local, which the team documents in the README and stores in the shared IDE run configuration. Production sets DATABASE_URL. Note that the empty default ${DATABASE_URL:} still fails fast with the same message when the variable is missing, which is exactly what you want in production: a clear startup failure instead of a half-working service.

Common mistake

The most tempting wrong fix is @SpringBootApplication(exclude = DataSourceAutoConfiguration.class) because a Stack Overflow answer said so. The application starts, and the problem moves: the first repository call fails, or JPA auto-configuration fails with a missing entityManagerFactory, or a JdbcTemplate bean cannot be created. Exclusion is correct only when you have no database. If you do, it just hides the missing URL.

A second mistake is hardcoding the production password in application.properties to make the error disappear. Use environment variables, a secrets manager or a profile file that is not committed.

A third: adding H2 to the main classpath “to make it start”. Boot happily creates an in-memory database, the app runs against an empty schema, and data disappears on restart. Keep H2 in test scope unless you really want it.

Verify the behavior

Prove both directions with ApplicationContextRunner, which runs only the auto-configurations you list and is fast:

import static org.assertj.core.api.Assertions.assertThat;

import javax.sql.DataSource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;

class DataSourceConfigurationTest {

    private final ApplicationContextRunner runner = new ApplicationContextRunner()
            .withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class));

    @Test
    void createsDataSourceWhenUrlIsSet() {
        runner.withPropertyValues("spring.datasource.url=jdbc:h2:mem:orders")
              .run(context -> assertThat(context).hasSingleBean(DataSource.class));
    }

    @Test
    void failsWithoutUrlOrEmbeddedDatabase() {
        runner.withClassLoader(new FilteredClassLoader("org.h2", "org.hsqldb", "org.apache.derby"))
              .run(context -> assertThat(context).hasFailed());
    }
}
java

This test assumes H2 is a test dependency. For the full application, a @SpringBootTest with @ActiveProfiles("local") (or Testcontainers) confirms the profile wiring. At runtime, a successful start logs HikariPool-1 - Start completed. from com.zaxxer.hikari.HikariDataSource.

Interview exercise

“Your service starts fine on your laptop but fails in CI with ‘Failed to configure a DataSource’. Nobody changed the code. How do you investigate?”

Answer and reasoning

Start from the failure analysis, not the code. The Action: section prints which profiles are active, so compare that with the laptop: an IDE run configuration or a shell variable such as SPRING_PROFILES_ACTIVE often supplies a profile locally that CI lacks. Next, check where the URL comes from on the laptop: a profile file, an environment variable like SPRING_DATASOURCE_URL (relaxed binding maps it to spring.datasource.url), or an untracked application-local.yml ignored by Git. Then check the classpath: if the laptop has H2 on the runtime classpath through a dev dependency, Boot silently used an embedded database there. The fix is to make configuration explicit per environment, inject the CI URL as a variable or use Testcontainers, and keep the fail-fast behaviour rather than excluding auto-configuration.

Continue learning

More in Spring Boot

read ✓Spring Boot · hard

Spring @Async and Executor Configuration

Run methods asynchronously with @Async, configure a bounded executor, and handle exceptions and the proxy boundary.

~2 min readread →
read ✓Spring Boot · hard

Spring Boot Caching Abstraction

Cache method results with @Cacheable, choose keys and TTLs, and evict on writes without the self-invocation trap.

~2 min readread →
read ✓Spring Boot · hard

Spring Declarative HTTP Clients

Define outbound HTTP as an annotated interface with @HttpExchange, create the proxy, and configure timeouts and errors.

~2 min readread →
esc