application.yml from Libraries Can Override or Be Silently Ignored — No Merging or Warning #11703
Labels
status: under consideration
The issue is being considered, but has not been accepted yet
type: enhancement
New feature or request
Expected Behavior
In this scenario, where a Micronaut application defines
application.yaml
and a library dependency provides its ownapplication.yml
, the expected behavior is:The application's configuration (
application.yaml
) should always take precedence.This aligns with developer expectations — the application's own config should never be overridden silently by a transitive library dependency.
Library configuration files should be loaded optionally and with transparency.
If a library provides its own
application.yml
, it may contain useful default values. These should be:When multiple
application.yml
or.yaml
files are found, Micronaut should:Ideally, Micronaut would support a configurable loading strategy, so developers can explicitly opt into:
FIRST_MATCH
(current behavior)MERGE_ALL
FAIL_ON_DUPLICATE
APP_ONLY
,APP_OVERRIDES_LIBS
)This approach ensures application authors retain full control over configuration while allowing library authors to provide sensible defaults without risk of overriding or being silently ignored.
Actual Behaviour
We created a reproducible Gradle multi-module Micronaut project with:
app
module that definesapplication.yaml
library
module that defines its ownapplication.yml
Expected: The application's config (
application.yaml
) should be loaded and take precedence.Actual: The application's config is silently ignored — only the library's
application.yml
is used.There are no logs, warnings, or exceptions indicating this override has occurred.
🔬 Why This Happens: Deep Dive into Micronaut’s
YamlPropertySourceLoader
The root cause lies in the
YamlPropertySourceLoader
, which extendsAbstractPropertySourceLoader
. Here’s the key method inAbstractPropertySourceLoader
:Build the Project:
Run the Application:
Observe the Output:
Notice that the configuration value from
app/src/main/resources/application.yaml
is not printed.Instead, the value from
utilities/src/main/resources/application.yml
is used.Modify the Project:
Open
app/build.gradle
and comment out the following line:implementation(project(":utilities"))
Rebuild and Rerun the Application:
Observe the Output Again:
Now, the configuration value from
app/src/main/resources/application.yaml
is printed as expected.These steps demonstrate the issue where the
application.yml
from theutilities
module overrides theapplication.yaml
from theapp
module.Environment Information
MacOS: 15.3.2 (24D81)
Java 21
Built tool: gradle
Example Application
https://github.com/tmellanxt/micronaut-yaml-bug
Version
4.7.6
🙋♂️ Contributor Statement
I am happy to contribute a fix for this issue and would appreciate guidance from the Micronaut team on the preferred direction. Specifically:
micronaut.config.load-strategy=FIRST_MATCH | MERGE_ALL | FAIL_ON_DUPLICATE
, etc.Additionally, it’s worth noting that this issue affects not just applications being overridden by libraries, but also cases where multiple libraries provide their own
application.yml
. In those cases, only one is loaded, and the rest are silently ignored, which can also break expected behavior unless libraries explicitly configure environment profiles or load configs differently.The text was updated successfully, but these errors were encountered: