{"record":{"id":"567b4bbbd0bda30a","repo":"stride3d/stride","slug":"cannot-unregister-a-service-on-a-nullserviceprovider","errorCode":null,"errorMessage":"Cannot unregister a service on a NullServiceProvider.","messagePattern":"Cannot unregister a service on a NullServiceProvider\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/presentation/Stride.Core.Presentation/ViewModels/NullServiceProvider.cs","lineNumber":30,"sourceCode":"    // to implement as they are part of the IViewModelServiceProvider definition.\n    /// <inheritdoc/>\n    public event EventHandler<ServiceRegistrationEventArgs>? ServiceRegistered { add { } remove { } }\n\n    // We provide an empty `add' and `remove' to avoid a warning about unused events that we have\n    // to implement as they are part of the IViewModelServiceProvider definition.\n    /// <inheritdoc/>\n    public event EventHandler<ServiceRegistrationEventArgs>? ServiceUnregistered { add { } remove { } }\n\n    /// <inheritdoc/>\n    public void RegisterService(object service)\n    {\n        throw new InvalidOperationException(\"Cannot register a service on a NullServiceProvider.\");\n    }\n\n    /// <inheritdoc/>\n    public void UnregisterService(object service)\n    {\n        throw new InvalidOperationException(\"Cannot unregister a service on a NullServiceProvider.\");\n    }\n\n    /// <inheritdoc/>\n    public object? TryGet(Type serviceType)\n    {\n        return null;\n    }\n\n    /// <inheritdoc/>\n    public T? TryGet<T>() where T : class\n    {\n        return null;\n    }\n\n    /// <inheritdoc/>\n    public object Get(Type serviceType)\n    {\n        throw new InvalidOperationException(\"No service matches the given type.\");","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/presentation/Stride.Core.Presentation/ViewModels/NullServiceProvider.cs#L12-L48","documentation":"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.","triggerScenarios":"Calling UnregisterService on a NullServiceProvider instance, or code that unconditionally unregisters services from whatever provider a view model exposes.","commonSituations":"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.","solutions":["Guard cleanup code to skip unregistration when the provider is NullServiceProvider","Use a real provider wherever services are registered/unregistered","Make disposal paths provider-type aware","Check TryGet result before unregistering"],"exampleFix":"// before\nprovider.UnregisterService(myService); // throws on NullServiceProvider\n// after\nif (provider is not NullServiceProvider) provider.UnregisterService(myService);","handlingStrategy":"type-guard","validationCode":"if (provider is NullServiceProvider) return; // nothing to unregister","typeGuard":"static bool SupportsUnregister(IViewModelServiceProvider p) => p is not NullServiceProvider;","tryCatchPattern":"try { provider.UnregisterService(service); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"NullServiceProvider\")) { /* ignore: null provider holds nothing */ }","preventionTips":["Branch cleanup logic on provider type","Skip unregistration for NullServiceProvider instances","Track which services were registered on which provider"],"tags":["service-provider","null-object","unregister","viewmodel"],"backgroundTag":"unsupported-operation","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}