dotnet dependency_injection ai_generated true

System.InvalidOperationException: No service for type 'X' has been registered

ID: dotnet/di-missing-registration

Also available as: JSON · Markdown
93%Fix Rate
90%Confidence
95Evidence
2020-01-01First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
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.

generic

Workarounds

  1. 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

  2. 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

  3. 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 incomplete

    Sources: https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection#scope-validation

Dead Ends

Common approaches that don't work:

  1. 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.

  2. 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.

Error Chain

Leads to:
Preceded by:
Frequently confused with: