{"record":{"id":"ebf863fbfeec5c8d","repo":"dotnet/yarp","slug":"at-least-one-iproxyconfigprovider-is-required","errorCode":null,"errorMessage":"At least one IProxyConfigProvider is required.","messagePattern":"At least one IProxyConfigProvider is required\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"critical","filePath":"src/ReverseProxy/Management/ProxyConfigManager.cs","lineNumber":103,"sourceCode":"        ArgumentNullException.ThrowIfNull(configChangeListeners);\n        ArgumentNullException.ThrowIfNull(destinationResolver);\n\n        _logger = logger;\n        _providers = providers.ToArray();\n        _clusterChangeListeners = clusterChangeListeners.ToArray();\n        _filters = filters.ToArray();\n        _configValidator = configValidator;\n        _proxyEndpointFactory = proxyEndpointFactory;\n        _transformBuilder = transformBuilder;\n        _httpClientFactory = httpClientFactory;\n        _activeHealthCheckMonitor = activeHealthCheckMonitor;\n        _clusterDestinationsUpdater = clusterDestinationsUpdater;\n        _destinationResolver = destinationResolver;\n        _configChangeListeners = configChangeListeners.ToArray();\n\n        if (_providers.Length == 0)\n        {\n            throw new ArgumentException($\"At least one {nameof(IProxyConfigProvider)} is required.\", nameof(providers));\n        }\n\n        _configs = new ConfigState[_providers.Length];\n\n        _conventions = new List<Action<EndpointBuilder>>();\n        DefaultBuilder = new ReverseProxyConventionBuilder(_conventions);\n\n        _endpointsChangeToken = new CancellationChangeToken(_endpointsChangeSource.Token);\n    }\n\n    public ReverseProxyConventionBuilder DefaultBuilder { get; }\n\n    // EndpointDataSource\n\n    /// <inheritdoc/>\n    public override IReadOnlyList<Endpoint> Endpoints\n    {\n        get","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/dotnet/yarp/blob/bd11867bee7df522e7fd3effb08a9c85fd616908/src/ReverseProxy/Management/ProxyConfigManager.cs#L85-L121","documentation":"The `ProxyConfigManager` constructor requires at least one `IProxyConfigProvider` to be registered in the DI container. YARP's configuration model is entirely driven by config providers (e.g., `LoadFromConfig`, `InMemoryConfigProvider`, or custom implementations). If none are registered, the proxy has no routes or clusters and cannot function, so construction fails immediately with an `ArgumentException`.","triggerScenarios":"`services.AddReverseProxy()` is called but no `.LoadFromConfig(...)` or `.LoadFromMemory(...)` follows it before the application starts. The `ProxyConfigManager` receives an empty `IProxyConfigProvider[]` array from DI and throws at line 103. This surfaces as a startup crash during service resolution.","commonSituations":"A developer adds `AddReverseProxy()` during initial scaffolding but hasn't yet wired up a config source. A developer writes a custom config provider but forgets to register it in DI. Someone removes the `.LoadFromConfig(configuration)` call while refactoring Program.cs.","solutions":["Call `.LoadFromConfig(builder.Configuration.GetSection(\"ReverseProxy\"))` after `AddReverseProxy()` to register the configuration-based provider.","Alternatively, call `.LoadFromMemory(routes, clusters)` to provide routes and clusters programmatically.","If using a custom `IProxyConfigProvider`, register it with `services.AddSingleton<IProxyConfigProvider, MyCustomProvider>()` before the proxy starts.","Verify in `Program.cs` that the `AddReverseProxy()` chain includes at least one config-loading method before `app.Run()`."],"exampleFix":"// before — no config provider registered, throws at startup\nbuilder.Services.AddReverseProxy();\n// after — load from appsettings.json\nbuilder.Services\n    .AddReverseProxy()\n    .LoadFromConfig(builder.Configuration.GetSection(\"ReverseProxy\"));\n// or load from memory\nbuilder.Services\n    .AddReverseProxy()\n    .LoadFromMemory(myRoutes, myClusters);","handlingStrategy":"validation","validationCode":"// After AddReverseProxy, verify a provider is registered\nvar providers = builder.Services.Where(s => s.ServiceType == typeof(IProxyConfigProvider)).ToList();\nif (providers.Count == 0)\n    throw new InvalidOperationException(\"AddReverseProxy requires at least one config provider via LoadFromConfig or LoadFromMemory\");","typeGuard":"// No type guard — this is a DI registration completeness check.","tryCatchPattern":"// Not applicable — this is a startup-time validation error.\n// Fix by registering a config provider.","preventionTips":["Always chain `.LoadFromConfig(...)` or `.LoadFromMemory(...)` after `.AddReverseProxy()`.","Add a startup assertion that verifies at least one IProxyConfigProvider is registered.","Review Program.cs after refactoring to ensure the config-loading chain is intact."],"tags":["configuration","startup","di","config-provider"],"backgroundTag":null,"analyzedSha":"bd11867bee7df522e7fd3effb08a9c85fd616908","analyzedAt":"2026-08-13T21:29:49.359Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}