Repository navigation
IServiceScope.Dispose() and DisposeAsync() should not stop disposing other services if one throws an exception #113563
Description
Activity
- addeduntriagedNew issue has not been triaged by the area ownerNew issue has not been triaged by the area owner
on Mar 15, 2025 dotnet-policy-service commented
on Mar 15, 2025 ContributorMore actionsTagging subscribers to this area: @dotnet/area-extensions-dependencyinjection
See info in area-owners.md if you want to be subscribed.IDisposable.Dispose() should not throw exceptions, according to CA1065: Do not raise exceptions in unexpected locations. Windows Communication Foundation (WCF) is known to violate this, though.
If service A depends on service B, and A.Dispose() throws but B.Dispose() is then called, it might cause problems later if A continues to use B. For example, B rents memory from a pool, A starts an asynchronous operation that writes to the memory, A.Dispose() fails to abort the operation, B.Dispose() returns the memory to the pool, and C rents the same memory while the operation started by A is still writing to it. For that reason, I think M.E.DI should not be changed to continue disposal of services after the first exception, by default; but an opt-in feature would be possible. If the opt-in were in ServiceProviderOptions, it would not need to be supported in other IServiceProvider implementations.
@mohammadKhalafi can't you create a decorator for your problematic type that wraps
Disposein a try/catch block?I would hate to see a framework/extensions class be updated to accomodate such a bad practice, as it would basically indirectly encourage its use.
I think an opt-in option makes sense, however it is low-priority at this time since it has not been requested in the past, at least based on some simple searches.
Moving to future to gauge interest \ feasibility.
- addedapi-suggestionEarly API idea and discussion, it is NOT ready for implementationEarly API idea and discussion, it is NOT ready for implementationand removeduntriagedNew issue has not been triaged by the area ownerNew issue has not been triaged by the area owner
on Mar 24, 2025 I think it's actually a good thing for the framework to provide an escape hatch for cases where a bad practice exists in an application—especially when it might come from an external library.
At the very least, when creating a scope, there could be an option that gives full control over disposal to the user. This way, disposal of the scope wouldn’t automatically dispose of all the disposables resolved from it, allowing users to manage disposal as they see fit.
I imagine M.E.DI would define some interface IDisposableTracker : IDisposable { void Add(IDisposable); } and let the application provide an instance of that; then the container would add disposable services to that as it creates them. Disposing the IServiceScope would dispose the IDisposeTracker, and that would be responsible of disposing the services and handling exceptions.
Unclear about this scheme:
- How does the application provide the IDisposableTracker: is it a parameter of CreateScope or a property of ServiceProviderOptions, or can it be registered as a service itself? In the latter case, can other services be injected to it?
- If one later wants to extend this so that the IDisposableTracker is also given some information from the ServiceDescriptor (especially ServiceType and ServiceKey), how does one do that without breaking the API?
- What happens if IDisposableTracker.Add calls back to the IServiceProvider, requesting another service from there?
- If IDisposableTracker.Add throws an exception, how is that handled? Does it cause M.E.DI to immediately dispose the service that could not be added?
- locked and limited conversation to collaborators
on Mar 30, 2026
Currently, in .NET, when using IServiceScope, if multiple services registered in the scope implement IDisposable or IAsyncDisposable, an exception in Dispose() or DisposeAsync() prevents the remaining services from being disposed when the scope is being disposed.
This can lead to memory leaks and unreleased resources