Skip to content

Config refresh fails and leaves refreshScope DOWN when spring.datasource.connection-fetch=lazy is used #1778

Closed

Description

@tommyk-gears

Versions: Spring Boot 4.1.2, Spring Cloud 2025.1.4 (spring-cloud-context 5.0.4), HikariCP. Also seen with Spring Cloud 2025.1.3 (spring-cloud-context 5.0.3), with a worse outcome (see below).

Reproducer: https://github.com/tommyk-gears/spring-cloud-lazy-datasource-refresh. Running ./gradlew test shows the failure: the same refresh scenario fails with connection-fetch=lazy and passes with connection-fetch=eager.

What happens

With spring.datasource.connection-fetch=lazy, a config refresh (POST /actuator/refresh, or ContextRefresher.refresh()) fails:

  • The refresh throws IllegalArgumentException: 'existingValue' must be an instance of com.zaxxer.hikari.HikariDataSource, and POST /actuator/refresh returns 500.
  • The refreshScope health indicator is DOWN from then on, so the overall health is DOWN too. It doesn't recover without a restart.
  • With spring-cloud-context 5.0.3, every query also fails from then on, with IllegalStateException: No 'targetDataSource' set. With 5.0.4 queries keep working (explained below).

In Kubernetes, this got our pods restarted by the liveness probe after a config refresh, and on 5.0.3 they served database errors until then. Without lazy connection fetching, the same refresh has no effect on the DataSource.

What we found

With lazy fetching, Boot's LazyConnectionDataSourceConfiguration wraps the @ConfigurationProperties HikariDataSource bean dataSource in a LazyConnectionDataSourceProxy, using a BeanPostProcessor. ConfigurationPropertiesRebinder rebinds the bean returned by getBean("dataSource"), which is the proxy. The proxy's class isn't in spring.cloud.refresh.never-refreshable, so the rebinder resets it and then binds the Hikari properties onto it. That binding fails, because the binding target from the bean definition is HikariDataSource.

Why queries only fail on 5.0.3: before rebinding, the rebinder resets the bean to the defaults of a fresh instance, and a fresh LazyConnectionDataSourceProxy has no target. 5.0.3 does this for any class with a no-arg constructor, so the proxy's target becomes null. 5.0.4 only does it for classes whose only constructor takes no arguments (gh-1733). LazyConnectionDataSourceProxy also has a LazyConnectionDataSourceProxy(DataSource) constructor, so the reset is skipped and the target is kept. With debug logging, 5.0.4 logs No default constructor for org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy; skipping property reset before rebinding.

Workaround

Add org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy to spring.cloud.refresh.never-refreshable. As documented for #1746, a custom value replaces the default, so com.zaxxer.hikari.HikariDataSource has to be listed too.

Possible directions, just as food for thought

  • Rebind the instance recorded by ConfigurationPropertiesBeans, i.e. the object the properties were bound to, rather than the post-processed bean. That also covers a wrapped DataSource type that does support rebinding.
  • Include LazyConnectionDataSourceProxy in the default never-refreshable value. That only skips the proxy (fine for Hikari, but a rebindable target would no longer be rebound), and like the Hikari default it is lost when a service sets its own value.

Activity

  1. added this to the 5.0.5 milestone on Oct 27, 2026
  2. moved this from Todo to In Progress in 2025.1.5on Oct 27, 2026
  3. moved this from Todo to In Progress in 2026.0.0-RC2on Oct 27, 2026
  4. ryanjbaxter commented on Oct 27, 2026

    @ryanjbaxter
    Contributor

    Thanks @tommyk-gears.

    Can you test the fix in #1779 to validate it addresses the issue?

  5. tommyk-gears commented on Oct 27, 2026

    @tommyk-gears
    ContributorAuthor

    Thanks @ryanjbaxter! I tested #1779 (c75dd966), built locally as spring-cloud-context 5.0.5-SNAPSHOT:

    Looks good to me.

  6. added a commit that references this issue on Oct 27, 2026
    c75dd96
  7. moved this from In Progress to Done in 2025.1.5on Oct 27, 2026
  8. moved this from In Progress to Done in 2026.0.0-RC2on Oct 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions