{"record":{"id":"d945204bfbba5946","repo":"RicoSuter/NSwag","slug":"api-explorer-not-registered-in-di","errorCode":null,"errorMessage":"API Explorer not registered in DI.","messagePattern":"API Explorer not registered in DI\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/NSwag.AspNetCore/Middlewares/OpenApiDocumentMiddleware.cs","lineNumber":45,"sourceCode":"        private int _version;\n        private readonly object _documentsCacheLock = new object();\n        private readonly Dictionary<string, Tuple<string, ExceptionDispatchInfo, DateTimeOffset>> _documentsCache = [];\n\n        /// <summary>Initializes a new instance of the <see cref=\"OpenApiDocumentMiddleware\"/> class.</summary>\n        /// <param name=\"nextDelegate\">The next delegate.</param>\n        /// <param name=\"serviceProvider\">The service provider.</param>\n        /// <param name=\"documentName\">The document name.</param>\n        /// <param name=\"path\">The document path.</param>\n        /// <param name=\"settings\">The settings.</param>\n        public OpenApiDocumentMiddleware(RequestDelegate nextDelegate, IServiceProvider serviceProvider, string documentName, string path, OpenApiDocumentMiddlewareSettings settings)\n        {\n            _nextDelegate = nextDelegate;\n\n            _documentName = documentName;\n            _path = path.StartsWith('/') ? path : '/' + path;\n\n            _apiDescriptionGroupCollectionProvider = serviceProvider.GetService<IApiDescriptionGroupCollectionProvider>() ??\n                throw new InvalidOperationException(\"API Explorer not registered in DI.\");\n            _documentProvider = serviceProvider.GetService<OpenApiDocumentProvider>() ??\n                throw new InvalidOperationException(\"The NSwag DI services are not registered: Call \" + nameof(NSwagServiceCollectionExtensions.AddSwaggerDocument) + \"() in ConfigureServices().\");\n\n            _settings = settings;\n        }\n\n        /// <summary>Invokes the specified context.</summary>\n        /// <param name=\"context\">The context.</param>\n        /// <returns>The task.</returns>\n        public async Task Invoke(HttpContext context)\n        {\n            if (context.Request.Path.HasValue && string.Equals(context.Request.Path.Value, _path, StringComparison.OrdinalIgnoreCase))\n            {\n                var schemaJson = await GetDocumentAsync(context);\n                context.Response.StatusCode = 200;\n                context.Response.Headers[\"Content-Type\"] = _path.Contains(\".yaml\", StringComparison.OrdinalIgnoreCase) ?\n                    \"application/yaml; charset=utf-8\" :\n                    \"application/json; charset=utf-8\";","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/RicoSuter/NSwag/blob/63daf8fcc3a25151b62eb4b326a1e8ea048a0d41/src/NSwag.AspNetCore/Middlewares/OpenApiDocumentMiddleware.cs#L27-L63","documentation":"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.').","triggerScenarios":"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.","commonSituations":"Minimal APIs without AddEndpointsApiExplorer/AddApiExplorer; hosting NSwag middleware in a bare WebApplication or non-MVC host; upgrading to minimal hosting and dropping explorer registration.","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."],"exampleFix":"// before\nvar app = builder.Build();\napp.UseOpenApi();\n// after\nbuilder.Services.AddEndpointsApiExplorer();\nbuilder.Services.AddOpenApiDocument();\nvar app = builder.Build();\napp.UseOpenApi();","handlingStrategy":"validation","validationCode":"// before UseOpenApi\nif (!builder.Services.Any(d => d.ServiceType.Name == \"IApiDescriptionGroupCollectionProvider\"))\n    builder.Services.AddEndpointsApiExplorer();","typeGuard":"bool ApiExplorerRegistered(IServiceProvider sp) => sp.GetService<Microsoft.AspNetCore.Mvc.ApiExplorer.IApiDescriptionGroupCollectionProvider>() != null;","tryCatchPattern":"try { app.UseOpenApi(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"API Explorer not registered\")) { logger.LogError(ex, \"Call AddEndpointsApiExplorer()/AddMvc() before UseOpenApi\"); throw; }","preventionTips":["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."],"tags":["aspnetcore","dependency-injection","api-explorer","startup"],"backgroundTag":"missing-dependency","analyzedSha":"63daf8fcc3a25151b62eb4b326a1e8ea048a0d41","analyzedAt":"2026-09-14T11:38:15.205Z","contentChangedAt":"2026-09-14T11:38:15.205Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}