# Unable to Resolve Service for Type in ASP.NET Core: Causes and Fixes

You start the API, hit any endpoint on a controller, and the request dies before a single line of your code runs:

```text
System.InvalidOperationException: Unable to resolve service for type
'MyApp.Application.Interfaces.IOrderService' while attempting to activate
'MyApp.Api.Controllers.OrdersController'.
```

The **unable to resolve service for type** error is the ASP.NET Core dependency injection container telling you something very specific: a constructor asked for a type, and the container has no idea how to build it. In production I've seen this exact message stop a Friday deploy cold, and in almost every case the root cause was one of seven things. This article walks through all of them, with the fix for each and the diagnostic that tells you which one you are looking at. If you want the same DI wiring shown inside a complete, runnable API rather than in isolated snippets, the annotated source on [Patreon](https://www.patreon.com/CodingDroplets) has the whole container setup wired end to end.

The reason this error is so common is that registration and consumption live in two different files, and nothing checks that they agree until runtime. Getting that right in a real codebase means designing the interface, the implementation, and the registration as one unit. [Chapter 3 of the Zero to Production course](https://aspnetcoreapi.codingdroplets.com/) builds exactly that pairing - `IProductRepository` and its implementation, registered and consumed inside a working ASP.NET Core API - so the shape is obvious before it ever breaks.

[![ASP.NET Core Web API: Zero to Production](https://newsletter.codingdroplets.com/images/aspnet-core-api-course-banner-1.jpg align="center")](https://aspnetcoreapi.codingdroplets.com/)

Everything below is verified against .NET 10 and the built-in `Microsoft.Extensions.DependencyInjection` container.

## What Does "Unable to Resolve Service for Type" Actually Mean?

It means the container was asked to construct a type, walked its constructor parameters, and hit one it has no registration for. The exception is thrown at **activation time**, not at startup, which is why the app boots fine and only fails when a request arrives.

Read the message as two halves:

*   `Unable to resolve service for type 'X'` - X is the missing registration. This is the thing you forgot.
    
*   `while attempting to activate 'Y'` - Y is the consumer. This is where the request was made from.
    

So `Unable to resolve service for type 'IOrderService' while attempting to activate 'OrdersController'` means: `OrdersController` has a constructor parameter of type `IOrderService`, and nothing in `Program.cs` maps `IOrderService` to a concrete class.

One nuance that trips people up constantly: the type named in the message is not always the one you registered wrong. If `IOrderService` is registered but `OrderService` takes an `IPricingEngine` that is not, the container reports the failure against the type it could not build. Always read the whole chain before assuming the top-level service is the culprit.

## Cause 1: The Service Was Never Registered

This is the overwhelming majority of real cases. The interface exists, the implementation exists, and nobody wired them together.

```csharp
// Program.cs - the registration that was missing
builder.Services.AddScoped<IOrderService, OrderService>();
```

Pick the lifetime deliberately rather than defaulting to `AddScoped` out of habit. `AddScoped` gives one instance per HTTP request and is the right default for anything touching `DbContext`. `AddSingleton` is for stateless, thread-safe services. `AddTransient` creates a new instance on every injection. If that decision is not obvious to you yet, our [DI lifetimes decision guide](https://codingdroplets.com/asp-net-core-di-lifetimes-singleton-vs-scoped-vs-transient-enterprise-decision-guide) breaks down where each one belongs.

**Fast diagnostic:** search the solution for the interface name. If the only two hits are the interface declaration and the constructor parameter, you have found it.

## Cause 2: You Registered the Concrete Type, Not the Interface

A subtle one, and the error message looks identical.

```csharp
// Registers OrderService. Does NOT register IOrderService.
builder.Services.AddScoped<OrderService>();
```

The container now knows how to build `OrderService`, but the controller asks for `IOrderService`, and that mapping does not exist. The two-generic-argument overload is what creates the mapping:

```csharp
builder.Services.AddScoped<IOrderService, OrderService>();
```

If you genuinely need both - some code injects the interface, other code injects the concrete class - register the mapping and then forward the concrete registration so you do not end up with two separate instances inside the same scope:

```csharp
builder.Services.AddScoped<OrderService>();
builder.Services.AddScoped<IOrderService>(sp => sp.GetRequiredService<OrderService>());
```

## Cause 3: A Dependency Deeper in the Chain Is Missing

The container resolves recursively. `OrdersController` needs `IOrderService`, `OrderService` needs `IPricingEngine`, `PricingEngine` needs `ITaxProvider`. Miss the registration at any level and activation fails.

The message points at the missing link, not at the controller. So if you see `Unable to resolve service for type 'ITaxProvider' while attempting to activate 'PricingEngine'`, the fix is at the bottom of the chain even though the symptom appeared at the top.

**Fast diagnostic:** the type in `attempting to activate` tells you which constructor to open. Walk that constructor's parameters against your registrations, one at a time.

## Cause 4: Registration Happens After the Container Is Built

Everything registered on `builder.Services` must be registered **before** `builder.Build()` is called. Anything after that point is either ignored or throws, because the service provider is already constructed.

```csharp
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<IOrderService, OrderService>();   // correct - before Build()

var app = builder.Build();
// Any Services.Add* here is too late.
```

This surfaces most often when someone factors registrations into an extension method and then calls it in the wrong place, or when a conditional registration sits behind an `if` that runs after `Build()`. Keep every registration in one clearly named block near the top of `Program.cs`.

## Cause 5: Open Generics Registered as Closed Types

Generic services need the open generic form. Registering a single closed type only satisfies that one closed type.

```csharp
// Only ever resolves IRepository<Order>.
builder.Services.AddScoped<IRepository<Order>, Repository<Order>>();

// Resolves IRepository<T> for every T.
builder.Services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
```

The second form uses the `typeof` overload with unbound generics. Miss it and you will get the error for every entity except the one you happened to register.

## Cause 6: A Missing Project Reference in a Layered Solution

In Clean Architecture solutions the interface lives in one project and the implementation in another. If the API project does not reference the Infrastructure project, the registration line will not even compile - but teams work around that by moving registration into an extension method inside Infrastructure, and then forget to call it.

```csharp
// Infrastructure/DependencyInjection.cs
public static IServiceCollection AddInfrastructure(this IServiceCollection services) =>
    services.AddScoped<IOrderRepository, OrderRepository>();
```

```csharp
// Program.cs - the call that was never added
builder.Services.AddInfrastructure();
```

**Fast diagnostic:** if your solution has an `AddApplication()` / `AddInfrastructure()` convention, check that every one of them is actually invoked in `Program.cs`. A missing call fails silently at startup and loudly on the first request.

## Cause 7: Injecting a Scoped Service Into a Singleton

This one produces a different but closely related exception:

```text
System.InvalidOperationException: Cannot consume scoped service
'MyApp.Data.AppDbContext' from singleton 'MyApp.Services.CacheWarmer'.
```

You have not forgotten a registration. You have created a **captive dependency**: a long-lived singleton holding a short-lived scoped instance, which would keep a `DbContext` alive for the life of the process. The container refuses on purpose.

The fix is to inject `IServiceScopeFactory` and create a scope where you need one:

```csharp
public sealed class CacheWarmer(IServiceScopeFactory scopeFactory) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken ct)
    {
        using var scope = scopeFactory.CreateScope();
        var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
        // use db inside this scope only
    }
}
```

That primary-constructor syntax requires C# 12 or later. This scenario shows up constantly in background services, and the closely related root-provider variant is covered in depth in our post on [cannot resolve scoped service from root provider](https://codingdroplets.com/cannot-resolve-scoped-service-root-provider-aspnet-core).

## How Do You Catch This Error at Startup Instead of at Runtime?

Turn on scope validation and eager validation so the container verifies every registration when the app starts rather than when a request arrives. In development this is on by default, but you have to opt in explicitly for other environments:

```csharp
builder.Host.UseDefaultServiceProvider(options =>
{
    options.ValidateScopes = true;
    options.ValidateOnBuild = true;
});
```

`ValidateOnBuild` walks every registration at `Build()` time and throws immediately for anything it cannot construct. `ValidateScopes` catches captive dependencies. Together they convert a per-request 500 into a deterministic startup crash, which is exactly what you want in CI.

The trade-off is honest: `ValidateOnBuild` adds a small amount of startup time proportional to the number of registrations. On every API I've shipped, that cost has been worth it. A container error that fails the pipeline is free; the same error discovered by a customer is not.

For anything that cannot be validated at build time - factory registrations, conditional wiring - a single integration test that spins up `WebApplicationFactory` and resolves every controller is a cheap safety net.

## Quick Reference: Symptom to Cause

| What the message says | Most likely cause |
| --- | --- |
| Type is your own interface, consumer is a controller | Never registered (Cause 1) |
| Type is an interface, concrete class is registered | Interface not mapped (Cause 2) |
| Consumer is a service, not a controller | Missing link deeper in the chain (Cause 3) |
| Registration clearly exists in the file | Registered after `Build()`, or extension method never called (Causes 4 and 6) |
| Type is generic, for example `IRepository<Invoice>` | Closed instead of open generic (Cause 5) |
| Message says "Cannot consume scoped service ... from singleton" | Captive dependency (Cause 7) |

## Frequently Asked Questions

### Why Does the App Start Fine and Only Fail When I Call an Endpoint?

Because controllers are activated per request, not at startup. The container does not attempt to construct `OrdersController` until a request routes to it, so a missing registration stays invisible until then. Enabling `ValidateOnBuild` moves the failure to startup, which is where you want it.

### What Is the Difference Between AddScoped, AddSingleton and AddTransient Here?

Lifetime does not affect whether the service resolves, only how many instances exist. A missing registration throws regardless of which lifetime you would have used. Lifetime becomes relevant for the captive dependency variant of the error, where a singleton cannot legally hold a scoped service.

### How Do I Fix "Unable to Resolve Service for Type DbContext"?

`AddDbContext<AppDbContext>()` registers the context as **scoped** by default. If the message names your `DbContext`, either the `AddDbContext` call is missing, or you are injecting the context into a singleton such as a `BackgroundService` or a hosted service. For the second case, inject `IServiceScopeFactory` and resolve the context inside a created scope.

### Can I Use Autofac or Scrutor to Avoid Registering Every Service by Hand?

Yes. Assembly-scanning registration removes an entire class of this error by convention-registering every `IFoo` to its matching `Foo`. It also makes the wiring less explicit, which is its own trade-off. We compare the options in [Autofac vs Scrutor vs Microsoft DI](https://codingdroplets.com/autofac-vs-scrutor-vs-microsoft-di-aspnet-core-2026).

### Why Does This Happen With Minimal APIs Too?

Minimal API endpoint handlers get their parameters from the same container. A handler parameter that is not a route value, query value or body is resolved as a service, so an unregistered type produces the same exception. Marking the parameter with `[FromServices]` makes the intent explicit and produces a clearer failure.

### Does the Official Microsoft Documentation Cover This?

The [dependency injection in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection) guide documents the registration APIs, lifetimes and scope validation behaviour in detail, and is the authoritative reference for the container's resolution rules.

## Wrapping Up

The **unable to resolve service for type** error is never mysterious once you read the message properly: the first type is what is missing, the second is who asked for it. Nine times out of ten the fix is a single line in `Program.cs`. The remaining cases are open generics, an uncalled registration extension method, or a captive dependency - and all three have a mechanical fix.

The durable improvement is not memorising the seven causes. It is turning on `ValidateOnBuild` and `ValidateScopes` so the container tells you about the problem in CI instead of in front of a user.

* * *

## About the Author

I'm Celin Daniel, Co-founder of [Coding Droplets](https://codingdroplets.com/). I've been building .NET and ASP.NET Core systems in production for 13+ years - APIs, distributed backends, enterprise platforms. Everything I write here comes from real shipping experience: patterns that held up, trade-offs that bit us, and lessons learned the hard way.

*   GitHub: [codingdroplets](http://github.com/codingdroplets/)
    
*   YouTube: [Coding Droplets](https://www.youtube.com/@CodingDroplets)
    
*   Website: [codingdroplets.com](https://codingdroplets.com/)
