Fix: Cannot resolve scoped service from root provider in .NET 8

Published: Jun 04, 2026 · By Kumar Kunal

The Error

You see this exception on app startup:

InvalidOperationException: Cannot resolve scoped service 'AppDbContext' from root provider.

Quick Fix - 30 Seconds

If you're running migrations or seeding data in Program.cs, wrap your code in a scope.

Wrong - Crashes:

var db = app.Services.GetService<AppDbContext>();
db.Database.Migrate(); // CRASH

Right - Works:

using var scope = app.Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
db.Database.Migrate(); // WORKS

Why This Happens

.NET's DI container has 3 lifetimes:

  1. Singleton: Created once. Lives for the entire app. Example: WebApplication.Services
  2. Scoped: Created once per HTTP request. Example: AppDbContext
  3. Transient: Created every time you ask for it

The rule: A Singleton cannot hold a Scoped service. app.Services is the root Singleton. AppDbContext is Scoped. ASP.NET blocks this to prevent memory leaks and disposed contexts.

Real-World Scenario: BackgroundService Injecting DbContext

#1 cause of this error in production. BackgroundService is Singleton, DbContext is Scoped:

// WRONG: Crashes on startup
public class OrderProcessor : BackgroundService
{
    private readonly AppDbContext _db; // Scoped service in Singleton
    
    public OrderProcessor(AppDbContext db) // DI throws InvalidOperationException
    {
        _db = db;
    }
}

// RIGHT: Use IServiceScopeFactory public class OrderProcessor : BackgroundService { private readonly IServiceScopeFactory _scopeFactory;

public OrderProcessor(IServiceScopeFactory scopeFactory)
{
    _scopeFactory = scopeFactory;
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    while (!stoppingToken.IsCancellationRequested)
    {
        using var scope = _scopeFactory.CreateScope(); // Dev Fix: New scope per loop
        var db = scope.ServiceProvider.GetRequiredService&lt;AppDbContext&gt;();
        
        var orders = await db.Orders.Where(o => o.Status == "Pending").ToListAsync(stoppingToken);
        // Process orders...
        
        await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
    }
}

}

Why this works: IServiceScopeFactory is Singleton. It creates a new scope for each work unit. DbContext is disposed after each loop, preventing memory leaks.

Related Fixes You Should Know

Root provider errors cascade into these:

FAQ

Q: Can I just make my DbContext a Singleton?

No. DbContext is not thread-safe and tracks entities. Making it Singleton causes data corruption and memory leaks. Always use Scoped or create per-operation with IServiceScopeFactory.

Q: Why does app.Services.GetService work in Minimal APIs but crash in Program.cs?

Minimal API endpoints run inside a request scope. Program.cs after builder.Build() runs at root scope. Different scopes, different rules.

Step-by-Step: How to Debug

  1. Check the stack trace: Error usually points to Program.cs after var app = builder.Build()
  2. Find app.Services.GetService<T>(): This uses the root provider
  3. Create a scope: using var scope = app.Services.CreateScope();
  4. Resolve from scope: scope.ServiceProvider.GetRequiredService<T>()

Related Dev Fixes

Found this helpful?

Master C# with our complete course. Real apps, real skills, job-ready in 2 hours.

Share this fix: Twitter LinkedIn

Comments on Fix: Cannot resolve scoped service from root provider in .NET 8 (0)

No comments yet. Be the first to share your thoughts!