dotnet/yarp · critical · InvalidOperationException

Unable to load or apply the proxy configuration.

Error message

Unable to load or apply the proxy configuration.

What it means

This is a wrapper exception thrown by the initial config-loading try-catch in `ProxyConfigManager.InitialLoadAsync`. Any exception during provider enumeration, config validation, route/cluster verification, destination resolution, or change-token wiring is caught and re-wrapped as `InvalidOperationException` with this message and the original exception as `InnerException`. The intent is to make startup config failures fatal and clearly attributed.

Source

Thrown at src/ReverseProxy/Management/ProxyConfigManager.cs:212

            var proxyConfigs = ExtractListOfProxyConfigs(_configs);

            foreach (var configChangeListener in _configChangeListeners)
            {
                configChangeListener.ConfigurationLoaded(proxyConfigs);
            }

            await ApplyConfigAsync(routes, clusters);

            foreach (var configChangeListener in _configChangeListeners)
            {
                configChangeListener.ConfigurationApplied(proxyConfigs);
            }

            ListenForConfigChanges();
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException("Unable to load or apply the proxy configuration.", ex);
        }

        // Initial active health check is run in the background.
        // Directly enumerate the ConcurrentDictionary to limit locking and copying.
        _ = _activeHealthCheckMonitor.CheckHealthAsync(_clusters.Select(pair => pair.Value));
        return this;
    }

    private async Task ReloadConfigAsync()
    {
        _configChangeSource.Dispose();

        var sourcesChanged = false;
        var routes = new List<RouteConfig>();
        var clusters = new List<ClusterConfig>();
        var reloadedConfigs = new List<(ConfigState Config, ValueTask<IProxyConfig> ResolveTask)>();

        // Start reloading changed configurations.

View on GitHub (pinned to bd11867bee)

Solutions

  1. Inspect `ex.InnerException` (and `InnerException.InnerException` for AggregateException) to find the root cause — the wrapper message alone is not actionable.
  2. If the inner exception is an `AggregateException` with validation errors, enumerate `innerException.InnerExceptions` to see each route/cluster validation failure individually.
  3. Use `IConfigValidator` diagnostics or the validation errors collection to identify the specific config field that is wrong.
  4. Validate your configuration file against the expected schema before deploying (route patterns, cluster IDs, header matcher modes, transform definitions).
  5. If using a custom config provider, add logging inside its `GetConfig()` to diagnose what data it produces.

Example fix

// To diagnose the real error, unwrap the chain at startup
catch (InvalidOperationException ex) when (ex.Message.Contains("Unable to load or apply"))
{
    var inner = ex.InnerException;
    if (inner is AggregateException agg)
    {
        foreach (var validationError in agg.InnerExceptions)
            Console.Error.WriteLine($"Config error: {validationError.Message}");
    }
    else
    {
        Console.Error.WriteLine($"Config load failed: {inner?.Message}");
    }
    throw;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate config before app starts
// Use IConfigValidator implementations to check config during a dry-run
var sp = builder.Services.BuildServiceProvider();
var configManager = sp.GetRequiredService<ProxyConfigManager>();
try { await configManager.InitialLoadAsync(); }
catch (InvalidOperationException ex) { /* log inner exceptions */ }

Type guard

// No type guard — this is a config-content validation issue.

Try / catch

try { await app.Services.GetRequiredService<ProxyConfigManager>().InitialLoadAsync(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Unable to load or apply"))
{
    var inner = ex.InnerException;
    if (inner is AggregateException agg)
        foreach (var e in agg.InnerExceptions) Console.Error.WriteLine(e.Message);
    else
        Console.Error.WriteLine(inner?.Message ?? ex.Message);
    throw;
}

Prevention

When it happens

Trigger: Any exception in the `InitialLoadAsync` try block (lines 171-208): a provider's `GetConfig()` throws, a config property is null, route/cluster validation fails, destination resolution fails, or `ApplyConfigAsync` throws. The outer catch at line 210 wraps it. The real cause is in `ex.InnerException` (and potentially `ex.InnerException.InnerException` for AggregateException from validation).

Common situations: The appsettings.json `ReverseProxy` section has malformed configuration (invalid route patterns, missing cluster IDs, duplicate routes, invalid header match rules). A custom config provider throws during initialization. Destination resolution (e.g., DNS) fails for a configured cluster. This is the most common startup failure in YARP.

Related errors


AI-assisted analysis of dotnet/yarp@bd11867bee (2026-08-13). Data as JSON: /api/errors/20999833ed17d66b. Report an issue: GitHub.