RicoSuter/NSwag · error · InvalidOperationException
API Explorer not registered in DI.
Error message
API Explorer not registered in DI.
What it means
OpenApiDocumentMiddleware relies on ASP.NET Core's IApiDescriptionGroupCollectionProvider, which is only registered when API Explorer services (AddApiExplorer / AddMvc with explorer) are present in the DI container. When resolving it via GetService returns null, the constructor throws InvalidOperationException('API Explorer not registered in DI.').
Solutions
- Call builder.Services.AddEndpointsApiExplorer() (minimal hosting) or services.AddApiExplorer() / AddMvc() in ConfigureServices.
- Verify services.AddOpenApiDocument()/AddSwaggerDocument() is called before building the pipeline.
- Ensure the middleware is added in the same app that registered the MVC/API Explorer services.
Example fix
// before var app = builder.Build(); app.UseOpenApi(); // after builder.Services.AddEndpointsApiExplorer(); builder.Services.AddOpenApiDocument(); var app = builder.Build(); app.UseOpenApi();
Defensive patterns
Strategy: validation
Validate before calling
// before UseOpenApi
if (!builder.Services.Any(d => d.ServiceType.Name == "IApiDescriptionGroupCollectionProvider"))
builder.Services.AddEndpointsApiExplorer(); Type guard
bool ApiExplorerRegistered(IServiceProvider sp) => sp.GetService<Microsoft.AspNetCore.Mvc.ApiExplorer.IApiDescriptionGroupCollectionProvider>() != null;
Try / catch
try { app.UseOpenApi(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("API Explorer not registered")) { logger.LogError(ex, "Call AddEndpointsApiExplorer()/AddMvc() before UseOpenApi"); throw; } Prevention
- Always pair UseOpenApi/UseSwagger with AddEndpointsApiExplorer (minimal hosting) or AddMvc/AddControllersWithViews (explorer included).
- In minimal APIs remember AddEndpointsApiExplorer is required even with AddSwaggerDocument.
- Add a startup check that resolves IApiDescriptionGroupCollectionProvider.
When it happens
Trigger: Mapping UseOpenApi()/UseSwagger() middleware in an app whose services were never registered with AddApiExplorer (or AddMvc/AddControllers variants that register it), so serviceProvider.GetService<IApiDescriptionGroupCollectionProvider>() returns null.
Common situations: Minimal APIs without AddEndpointsApiExplorer/AddApiExplorer; hosting NSwag middleware in a bare WebApplication or non-MVC host; upgrading to minimal hosting and dropping explorer registration.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- The NSwag DI services are not registered: Call…
- Unable to build IHost
- This UI does not support multiple documents per UI: Do not…
- The SwaggerUiRoute cannot contain
- The OpenAPI/Swagger document
AI-assisted analysis of RicoSuter/NSwag@63daf8fcc3 (2026-09-14).
Data as JSON: /api/errors/d945204bfbba5946.
Report an issue: GitHub.
Appendix: source
Thrown at src/NSwag.AspNetCore/Middlewares/OpenApiDocumentMiddleware.cs:45
private int _version;
private readonly object _documentsCacheLock = new object();
private readonly Dictionary<string, Tuple<string, ExceptionDispatchInfo, DateTimeOffset>> _documentsCache = [];
/// <summary>Initializes a new instance of the <see cref="OpenApiDocumentMiddleware"/> class.</summary>
/// <param name="nextDelegate">The next delegate.</param>
/// <param name="serviceProvider">The service provider.</param>
/// <param name="documentName">The document name.</param>
/// <param name="path">The document path.</param>
/// <param name="settings">The settings.</param>
public OpenApiDocumentMiddleware(RequestDelegate nextDelegate, IServiceProvider serviceProvider, string documentName, string path, OpenApiDocumentMiddlewareSettings settings)
{
_nextDelegate = nextDelegate;
_documentName = documentName;
_path = path.StartsWith('/') ? path : '/' + path;
_apiDescriptionGroupCollectionProvider = serviceProvider.GetService<IApiDescriptionGroupCollectionProvider>() ??
throw new InvalidOperationException("API Explorer not registered in DI.");
_documentProvider = serviceProvider.GetService<OpenApiDocumentProvider>() ??
throw new InvalidOperationException("The NSwag DI services are not registered: Call " + nameof(NSwagServiceCollectionExtensions.AddSwaggerDocument) + "() in ConfigureServices().");
_settings = settings;
}
/// <summary>Invokes the specified context.</summary>
/// <param name="context">The context.</param>
/// <returns>The task.</returns>
public async Task Invoke(HttpContext context)
{
if (context.Request.Path.HasValue && string.Equals(context.Request.Path.Value, _path, StringComparison.OrdinalIgnoreCase))
{
var schemaJson = await GetDocumentAsync(context);
context.Response.StatusCode = 200;
context.Response.Headers["Content-Type"] = _path.Contains(".yaml", StringComparison.OrdinalIgnoreCase) ?
"application/yaml; charset=utf-8" :
"application/json; charset=utf-8";View on GitHub (pinned to 63daf8fcc3)