-
Notifications
You must be signed in to change notification settings - Fork 171
Description
Bug Summary
The ConsulDiscoveryClient in Steeltoe V4 crashes with a System.ArgumentNullException when attempting to resolve a service instance that was registered in Consul without any Metadata (Meta). The ConsulServiceInstance constructor attempts to convert the service's metadata into a ReadOnlyDictionary without checking if the source dictionary is null.
GitHub Issue Template
You can copy and paste the content below directly into a new GitHub Issue.
Title:
[Bug] ArgumentNullException in ConsulServiceInstance when Service Metadata is null
Description:
I am using Steeltoe.Discovery.Consul (V4) to discover services registered in Consul. When the .NET client attempts to resolve a service instance (e.g., a Python FastAPI service) that was registered without any Metadata/Tags, the application crashes with a System.ArgumentNullException.
It appears that the ConsulServiceInstance constructor does not handle null values for Service.Meta before attempting to create a ReadOnlyDictionary.
Steps to Reproduce:
- Register a service in Consul (e.g., using
python-consulor raw HTTP API) without providing anyMetaorTagsdata.// Example Consul Service definition causing the issue { "Name": "fastapi-hello", "Port": 8000, "Meta": null }
- Configure a .NET 6/8 application with
AddServiceDiscovery()using Steeltoe V4. - Attempt to fetch instances using
IDiscoveryClient.GetInstancesAsync()or make a request using the configuredHttpClient.
Expected Behavior:
The client should handle null metadata gracefully (e.g., treat it as an empty dictionary) and successfully return the service instance.
Actual Behavior:
The application throws a System.ArgumentNullException originating from the ConsulServiceInstance constructor.
Stack Trace:
System.ArgumentNullException: Value cannot be null. (Parameter 'dictionary')
at System.ArgumentNullException.Throw(String paramName)
at System.Collections.ObjectModel.ReadOnlyDictionary`2..ctor(IDictionary`2 dictionary)
at System.Collections.Generic.CollectionExtensions.AsReadOnly[TKey,TValue](IDictionary`2 dictionary)
at Steeltoe.Discovery.Consul.ConsulServiceInstance..ctor(ServiceEntry serviceEntry) in /_/src/Discovery/src/Consul/ConsulServiceInstance.cs:line 48
at Steeltoe.Discovery.Consul.ConsulDiscoveryClient.<>c.<AddInstancesToListAsync>b__15_0(ServiceEntry entry)
at System.Linq.Enumerable.ArraySelectIterator`2.MoveNext()
at Steeltoe.Discovery.Consul.ConsulDiscoveryClient.AddInstancesToListAsync(...)
at Steeltoe.Discovery.Consul.ConsulDiscoveryClient.GetInstancesAsync(...)
at Steeltoe.Discovery.HttpClients.LoadBalancers.ServiceInstancesResolver.ResolveInstancesAsync(...)
Environment:
- Steeltoe Version: 4.0.x (Discovery.Consul)
- Target Framework: .NET 6 / .NET 8
- Consul Version: (Any)
Possible Fix / Workaround:
Currently, I have to ensure that non-NET services register with at least one dummy metadata entry (e.g., meta={"fix": "true"}) to prevent the client from crashing. The constructor in ConsulServiceInstance.cs should check for null before calling AsReadOnly.