You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Configuration data allows nullable values, but ChainedConfigurationProvider.TryGet doesn't work correctly with them #65594
If the inner configuration returned null, ChainedConfigurationProvider would return false, even though the it is possible the inner configuration provider returned true and value == null.
This feels like an issue with our API design here. Can null be a valid configuration value or not? If it can, should ChainedConfigurationProvider respect it?
I think the right behavior is for TryGet to return false if _config[key] is null but return true if its "". I'm not how much code out there today relies on falling back from chained config sources that return "". Hopefully not a lot.
I just ran into this behavior of the ChainedConfigurationProvider.
We have a configuration system that get its values from a database, but all values can be overwritten per environment or secrets. Environment and secrets come from the ChainedConfigurationProvider, while the database values have their own IConfigurationProvider implementation.
I wanted to overwrite one value with "" in the environment, but that did not happen due to the string.IsNullOrEmpty(value)check of theChainedConfigurationProvider`.
I agree with @halter73 that "" should return true, but we also had an internal discussion that this would probably not be fixed in the near future as it could harm existing code. 🙄
The current design results in a discrepancy between how Web Host and Generic Host read configuration data from appsettings.json files (presumably Generic Host uses ChainedConfigurationProvider). Web Host supports/returns empty strings verbatim as valid configuration values whereas Generic host interprets these as null.
This breaks the Sentry SDK when using Generic Host (which allows you to set the URL of your sentry server to string.Empty to disable the SDK):
Part of this issue was solved by #131480. What's left is that the ChainedConfigurationProvider can't distinguish between explicit null and missing value, since it reads IConfiguration where the two are both represented by null returned. What we can do collapses into two things:
We can unwrap our IConfiguration implementations, namely ConfigurationRoot and ConfigurationManager and iterate their providers (we discussed this point with @tarekgh in the mentioned PR and there is even a precedent of doing it in ConfigurationSection). Relatively easy and quick, however, we create a situation where 3rd party IConfiguration implementors won't be able to contribute to this behaviour because they can't implement IConfigurationRoot (and because it would be dangerous if we bypassed their IConfiguration indexer by iterating providers directly when we don't know if there is any additional logic in the indexer and we would break existing code). Threrefore, we should provide the way by adding a new interface they can implement:
If the 3rd party IConfiguration doesn't implement the interface, we fallback to interpreting null as missing key, which is what we do now so there shouldn't be any breaking change introduced.
Removing the bug label. The half of this that was genuinely a defect, an empty string being reported as absent, was fixed in #131480. What's left is that IConfiguration exposes only an indexer, so a chained configuration cannot distinguish "key absent" from "key present with a null value". That's a limitation of the abstraction rather than something ChainedConfigurationProvider gets wrong, and as @eerhardt put it originally, the real question is whether null is a valid configuration value at all.
Looks good to me. One small tweak could make it easier to extend the functionality in the future without having to modify the interface or worry about down-level support. That said, it's a minor detail, and I think the overall direction makes sense.
publicinterfaceIConfigurationQueryProvider{/// <summary>/// Returns an object that answers full-fidelity queries against this configuration,/// or <see langword="null"/> if not supported./// </summary>ConfigurationQuery?GetConfigurationQuery();}/// <summary>/// Answers full-fidelity queries against a configuration. This is an abstract class rather/// than an interface so new query operations can be added in future versions as virtual/// members with default implementations, without breaking existing implementers./// </summary>publicabstractclassConfigurationQuery{publicabstractboolTryGet(stringkey,outstring?value);publicabstractIEnumerable<string>GetChildKeys(IEnumerable<string>earlierKeys,string?parentPath);// Future capabilities are added here as VIRTUAL methods with a default body:}
CC @halter73. Note, this is something to support in the future and not for .NET 11.
Activity
maxkoshevoi commentedon Feb 19, 2022
Found the reason of why
out string? valuewasn't annotated with[NotNullWhen(true)]: #57414 (comment)halter73 commentedon Mar 17, 2022
I think the right behavior is for
TryGetto returnfalseif_config[key]isnullbut returntrueif its"". I'm not how much code out there today relies on falling back from chained config sources that return"". Hopefully not a lot.csnethaus commentedon Apr 10, 2024
I just ran into this behavior of the
ChainedConfigurationProvider.We have a configuration system that get its values from a database, but all values can be overwritten per environment or secrets. Environment and secrets come from the ChainedConfigurationProvider, while the database values have their own
IConfigurationProviderimplementation.I wanted to overwrite one value with
""in the environment, but that did not happen due to the string.IsNullOrEmpty(value)check of theChainedConfigurationProvider`.I agree with @halter73 that
""should returntrue, but we also had an internal discussion that this would probably not be fixed in the near future as it could harm existing code. 🙄jamescrosswell commentedon Jan 8, 2025
Just adding a vote here.
The current design results in a discrepancy between how Web Host and Generic Host read configuration data from appsettings.json files (presumably Generic Host uses ChainedConfigurationProvider). Web Host supports/returns empty strings verbatim as valid configuration values whereas Generic host interprets these as null.
This breaks the Sentry SDK when using Generic Host (which allows you to set the URL of your sentry server to string.Empty to disable the SDK):
Arguably the current behavioural inconsistencies are a bug then.
rosebyte commentedon Mar 3, 2026
Triage: this issue seems related to other issues on the chained configuration source, we will investigate the root cause and potentially fix it.
Treat empty string value from chained configuration as present (#131480)
rosebyte commentedon Aug 5, 2026
Part of this issue was solved by #131480. What's left is that the ChainedConfigurationProvider can't distinguish between explicit null and missing value, since it reads IConfiguration where the two are both represented by null returned. What we can do collapses into two things:
We can unwrap our IConfiguration implementations, namely ConfigurationRoot and ConfigurationManager and iterate their providers (we discussed this point with @tarekgh in the mentioned PR and there is even a precedent of doing it in ConfigurationSection). Relatively easy and quick, however, we create a situation where 3rd party IConfiguration implementors won't be able to contribute to this behaviour because they can't implement IConfigurationRoot (and because it would be dangerous if we bypassed their IConfiguration indexer by iterating providers directly when we don't know if there is any additional logic in the indexer and we would break existing code). Threrefore, we should provide the way by adding a new interface they can implement:
If the 3rd party IConfiguration doesn't implement the interface, we fallback to interpreting null as missing key, which is what we do now so there shouldn't be any breaking change introduced.
What do you think?
rosebyte commentedon Aug 5, 2026
Removing the
buglabel. The half of this that was genuinely a defect, an empty string being reported as absent, was fixed in #131480. What's left is thatIConfigurationexposes only an indexer, so a chained configuration cannot distinguish "key absent" from "key present with a null value". That's a limitation of the abstraction rather than somethingChainedConfigurationProvidergets wrong, and as @eerhardt put it originally, the real question is whethernullis a valid configuration value at all.tarekgh commentedon Aug 5, 2026
Looks good to me. One small tweak could make it easier to extend the functionality in the future without having to modify the interface or worry about down-level support. That said, it's a minor detail, and I think the overall direction makes sense.
CC @halter73. Note, this is something to support in the future and not for .NET 11.