System.InvalidOperationException: No service for type 'X' has been registered
ID: dotnet/di-missing-registration
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| 8 | active | — | — | — |
Root Cause
The .NET dependency injection container cannot resolve a service because it was never registered in the DI container (Program.cs / Startup.cs). This occurs when a controller, service, or middleware requests a dependency via constructor injection but the corresponding AddScoped/AddTransient/AddSingleton registration is missing. It also happens when registering a concrete type but injecting an interface that was not mapped, or when a transitive dependency of a registered service is itself unregistered.
genericWorkarounds
-
95% success Register the missing service in Program.cs with the appropriate lifetime
Add the missing registration in Program.cs (or Startup.cs for older patterns): var builder = WebApplication.CreateBuilder(args); // Register interface -> implementation mapping: builder.Services.AddScoped<IMyService, MyService>(); // Or register concrete type directly: builder.Services.AddTransient<MyService>(); // For services with dependencies, ensure ALL transitive dependencies are registered: builder.Services.AddScoped<IRepository, SqlRepository>(); builder.Services.AddScoped<IMyService, MyService>(); // MyService depends on IRepository // Common registrations often missed: builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("Default"))); builder.Services.AddHttpClient<IApiClient, ApiClient>(); builder.Services.AddMemoryCache(); builder.Services.AddScoped<ICurrentUserService, CurrentUserService>(); var app = builder.Build();Sources: https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection
-
88% success Use assembly scanning to auto-register services by convention
Use Scrutor or a custom convention to auto-register services and avoid missing registrations: // Install Scrutor: dotnet add package Scrutor builder.Services.Scan(scan => scan .FromAssemblyOf<MyService>() .AddClasses(classes => classes.AssignableTo<IScopedService>()) .AsImplementedInterfaces() .WithScopedLifetime() .AddClasses(classes => classes.AssignableTo<ITransientService>()) .AsImplementedInterfaces() .WithTransientLifetime() ); // Or use a simple custom convention: var serviceTypes = typeof(Program).Assembly.GetTypes() .Where(t => t.IsClass && !t.IsAbstract && t.Name.EndsWith("Service")); foreach (var type in serviceTypes) { var iface = type.GetInterfaces().FirstOrDefault(i => i.Name == $"I{type.Name}"); if (iface != null) builder.Services.AddScoped(iface, type); }Sources: https://github.com/khellang/Scrutor https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection
-
85% success Validate DI registrations at startup to catch missing registrations early
Enable scope validation in development to catch DI issues at startup instead of at runtime: // In Program.cs: var builder = WebApplication.CreateBuilder(args); // Enable scope validation (already on by default in Development): if (builder.Environment.IsDevelopment()) { builder.Host.UseDefaultServiceProvider(options => { options.ValidateScopes = true; options.ValidateOnBuild = true; // Catches missing registrations at startup! }); } // ValidateOnBuild will throw at app startup if any registered service // has a dependency that is not registered, giving you an immediate error // instead of a runtime exception when the service is first requested. var app = builder.Build(); // Throws here if DI graph is incompleteSources: https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection#scope-validation
Dead Ends
Common approaches that don't work:
-
Manually creating service instances with 'new' instead of registering in DI
85% fail
Creating instances manually with 'new ServiceX()' bypasses the DI container entirely. The manually created instance will not have its own dependencies injected, leading to NullReferenceExceptions deeper in the call chain. It also defeats the purpose of DI (testability, lifetime management, loose coupling) and creates tight coupling that makes unit testing impossible without the concrete implementation.
-
Using IServiceProvider.GetService() everywhere to avoid constructor injection
80% fail
Resolving services via IServiceProvider (Service Locator pattern) hides dependencies, makes the code harder to test, and can cause scoped services to be resolved outside their intended scope. It does not fix the missing registration -- GetService() returns null for unregistered services (leading to NullReferenceException later) and GetRequiredService() throws the same InvalidOperationException. The root cause is the missing registration, not the injection method.