dotnet/yarp · error · InvalidOperationException

ConfigureHttpClient will override the custom IForwarderHttpC

Error message

ConfigureHttpClient will override the custom IForwarderHttpClientFactory type.

What it means

`ConfigureHttpClient` registers a `CallbackHttpClientFactory` to apply custom `SocketsHttpHandler` settings. Before doing so, it checks whether a non-default `IForwarderHttpClientFactory` is already registered in DI. If a custom factory exists, YARP refuses to silently override it — this would lose the custom factory's behavior. The throw is a guard against accidental double-registration.

Source

Thrown at src/ReverseProxy/Management/ReverseProxyServiceCollectionExtensions.cs:160

    }

    /// <summary>
    /// Provides a callback to customize <see cref="SocketsHttpHandler"/> settings used for proxying requests.
    /// This will be called each time a cluster is added or changed. Cluster settings are applied to the handler before
    /// the callback. Custom data can be provided in the cluster metadata.
    /// </summary>
    public static IReverseProxyBuilder ConfigureHttpClient(this IReverseProxyBuilder builder, Action<ForwarderHttpClientContext, SocketsHttpHandler> configure)
    {
        ArgumentNullException.ThrowIfNull(configure);

        // Avoid overriding any other custom factories. This does not handle the case where a IForwarderHttpClientFactory
        // is registered after this call.
        var service = builder.Services.FirstOrDefault(service => service.ServiceType == typeof(IForwarderHttpClientFactory));
        if (service is not null)
        {
            if (service.ImplementationType != typeof(ForwarderHttpClientFactory))
            {
                throw new InvalidOperationException($"ConfigureHttpClient will override the custom IForwarderHttpClientFactory type.");
            }
        }

        builder.Services.AddSingleton<IForwarderHttpClientFactory>(services =>
        {
            var logger = services.GetRequiredService<ILogger<ForwarderHttpClientFactory>>();
            return new CallbackHttpClientFactory(logger, configure);
        });
        return builder;
    }

    /// <summary>
    /// Provides a <see cref="IDestinationResolver"/> implementation which uses <see cref="System.Net.Dns"/> to resolve destinations.
    /// </summary>
    public static IReverseProxyBuilder AddDnsDestinationResolver(this IReverseProxyBuilder builder, Action<DnsDestinationResolverOptions>? configureOptions = null)
    {
        builder.Services.AddSingleton<IDestinationResolver, DnsDestinationResolver>();
        if (configureOptions is not null)

View on GitHub (pinned to bd11867bee)

Solutions

  1. Choose one approach: either use `ConfigureHttpClient` for simple `SocketsHttpHandler` callbacks, or register a full custom `IForwarderHttpClientFactory` — not both.
  2. If you need both custom factory logic and handler configuration, fold the handler configuration into your custom factory's implementation instead of using `ConfigureHttpClient`.
  3. If the custom factory was registered by mistake or a library, remove the conflicting registration before calling `ConfigureHttpClient`.
  4. If you must use a custom factory, extend `ForwarderHttpClientFactory` and override the handler-creation logic rather than registering a different type.

Example fix

// before — conflicting registrations throw
builder.Services
    .AddReverseProxy()
    .AddCustomHttpClientFactory(); // registers custom IForwarderHttpClientFactory
builder.Services
    .AddReverseProxy()
    .ConfigureHttpClient((ctx, handler) =>
    {
        handler.MaxConnectionsPerServer = 100; // throws!
    });
// after — fold handler config into the custom factory
public class MyHttpClientFactory : ForwarderHttpClientFactory
{
    protected override SocketsHttpHandler CreateHandler(ForwarderHttpClientContext context)
    {
        var handler = base.CreateHandler(context);
        handler.MaxConnectionsPerServer = 100;
        return handler;
    }
}
// Register only the custom factory — no ConfigureHttpClient call
Defensive patterns

Strategy: validation

Validate before calling

// Before calling ConfigureHttpClient, check for existing custom factory
var existingFactory = builder.Services
    .FirstOrDefault(s => s.ServiceType == typeof(IForwarderHttpClientFactory));
if (existingFactory is not null && existingFactory.ImplementationType != typeof(ForwarderHttpClientFactory))
    throw new InvalidOperationException("A custom IForwarderHttpClientFactory is already registered; cannot call ConfigureHttpClient");

Type guard

// No type guard — this is a DI registration conflict, not a type-narrowing issue.

Try / catch

// Not applicable — fix the registration to use one approach, not both.

Prevention

When it happens

Trigger: `AddReverseProxy().ConfigureHttpClient(...)` is called after a custom `IForwarderHttpClientFactory` has already been registered via `services.AddSingleton<IForwarderHttpClientFactory, MyCustomFactory>()`. The check at line 158 finds `ImplementationType != typeof(ForwarderHttpClientFactory)` and throws. Note: this only catches factories registered *before* the `ConfigureHttpClient` call, not after.

Common situations: A developer registers a custom HttpClient factory for advanced pooling or certificate handling, then also calls `ConfigureHttpClient` for handler tweaks. Or a shared initialization method calls both approaches without realizing they conflict. A library that integrates with YARP registers its own factory, and the application also calls `ConfigureHttpClient`.

Related errors


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