stride3d/stride · error · InvalidOperationException

Cannot unregister a service on a NullServiceProvider.

Error message

Cannot unregister a service on a NullServiceProvider.

What it means

Symmetric with RegisterService: NullServiceProvider deliberately holds no services and returns null from all lookups, so UnregisterService has nothing meaningful to do. It throws InvalidOperationException to make the misuse loud instead of silently no-op'ing.

Solutions

  1. Guard cleanup code to skip unregistration when the provider is NullServiceProvider
  2. Use a real provider wherever services are registered/unregistered
  3. Make disposal paths provider-type aware
  4. Check TryGet result before unregistering

Example fix

// before
provider.UnregisterService(myService); // throws on NullServiceProvider
// after
if (provider is not NullServiceProvider) provider.UnregisterService(myService);
Defensive patterns

Strategy: type-guard

Validate before calling

if (provider is NullServiceProvider) return; // nothing to unregister

Type guard

static bool SupportsUnregister(IViewModelServiceProvider p) => p is not NullServiceProvider;

Try / catch

try { provider.UnregisterService(service); }
catch (InvalidOperationException ex) when (ex.Message.Contains("NullServiceProvider")) { /* ignore: null provider holds nothing */ }

Prevention

When it happens

Trigger: Calling UnregisterService on a NullServiceProvider instance, or code that unconditionally unregisters services from whatever provider a view model exposes.

Common situations: Teardown/cleanup paths written for real providers but executed against null providers in tests or disposed scenarios; shared disposal code that does not branch on provider type.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/567b4bbbd0bda30a. Report an issue: GitHub.

Appendix: source

Thrown at sources/presentation/Stride.Core.Presentation/ViewModels/NullServiceProvider.cs:30

    // to implement as they are part of the IViewModelServiceProvider definition.
    /// <inheritdoc/>
    public event EventHandler<ServiceRegistrationEventArgs>? ServiceRegistered { add { } remove { } }

    // We provide an empty `add' and `remove' to avoid a warning about unused events that we have
    // to implement as they are part of the IViewModelServiceProvider definition.
    /// <inheritdoc/>
    public event EventHandler<ServiceRegistrationEventArgs>? ServiceUnregistered { add { } remove { } }

    /// <inheritdoc/>
    public void RegisterService(object service)
    {
        throw new InvalidOperationException("Cannot register a service on a NullServiceProvider.");
    }

    /// <inheritdoc/>
    public void UnregisterService(object service)
    {
        throw new InvalidOperationException("Cannot unregister a service on a NullServiceProvider.");
    }

    /// <inheritdoc/>
    public object? TryGet(Type serviceType)
    {
        return null;
    }

    /// <inheritdoc/>
    public T? TryGet<T>() where T : class
    {
        return null;
    }

    /// <inheritdoc/>
    public object Get(Type serviceType)
    {
        throw new InvalidOperationException("No service matches the given type.");

View on GitHub (pinned to 96fad776d2)