{"record":{"id":"ad68622733b4a682","repo":"dotnet/yarp","slug":"configurehttpclient-will-override-the-custom-iforw","errorCode":null,"errorMessage":"ConfigureHttpClient will override the custom IForwarderHttpClientFactory type.","messagePattern":"ConfigureHttpClient will override the custom IForwarderHttpClientFactory type\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/ReverseProxy/Management/ReverseProxyServiceCollectionExtensions.cs","lineNumber":160,"sourceCode":"    }\n\n    /// <summary>\n    /// Provides a callback to customize <see cref=\"SocketsHttpHandler\"/> settings used for proxying requests.\n    /// This will be called each time a cluster is added or changed. Cluster settings are applied to the handler before\n    /// the callback. Custom data can be provided in the cluster metadata.\n    /// </summary>\n    public static IReverseProxyBuilder ConfigureHttpClient(this IReverseProxyBuilder builder, Action<ForwarderHttpClientContext, SocketsHttpHandler> configure)\n    {\n        ArgumentNullException.ThrowIfNull(configure);\n\n        // Avoid overriding any other custom factories. This does not handle the case where a IForwarderHttpClientFactory\n        // is registered after this call.\n        var service = builder.Services.FirstOrDefault(service => service.ServiceType == typeof(IForwarderHttpClientFactory));\n        if (service is not null)\n        {\n            if (service.ImplementationType != typeof(ForwarderHttpClientFactory))\n            {\n                throw new InvalidOperationException($\"ConfigureHttpClient will override the custom IForwarderHttpClientFactory type.\");\n            }\n        }\n\n        builder.Services.AddSingleton<IForwarderHttpClientFactory>(services =>\n        {\n            var logger = services.GetRequiredService<ILogger<ForwarderHttpClientFactory>>();\n            return new CallbackHttpClientFactory(logger, configure);\n        });\n        return builder;\n    }\n\n    /// <summary>\n    /// Provides a <see cref=\"IDestinationResolver\"/> implementation which uses <see cref=\"System.Net.Dns\"/> to resolve destinations.\n    /// </summary>\n    public static IReverseProxyBuilder AddDnsDestinationResolver(this IReverseProxyBuilder builder, Action<DnsDestinationResolverOptions>? configureOptions = null)\n    {\n        builder.Services.AddSingleton<IDestinationResolver, DnsDestinationResolver>();\n        if (configureOptions is not null)","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/dotnet/yarp/blob/bd11867bee7df522e7fd3effb08a9c85fd616908/src/ReverseProxy/Management/ReverseProxyServiceCollectionExtensions.cs#L142-L178","documentation":"`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.","triggerScenarios":"`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.","commonSituations":"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`.","solutions":["Choose one approach: either use `ConfigureHttpClient` for simple `SocketsHttpHandler` callbacks, or register a full custom `IForwarderHttpClientFactory` — not both.","If you need both custom factory logic and handler configuration, fold the handler configuration into your custom factory's implementation instead of using `ConfigureHttpClient`.","If the custom factory was registered by mistake or a library, remove the conflicting registration before calling `ConfigureHttpClient`.","If you must use a custom factory, extend `ForwarderHttpClientFactory` and override the handler-creation logic rather than registering a different type."],"exampleFix":"// before — conflicting registrations throw\nbuilder.Services\n    .AddReverseProxy()\n    .AddCustomHttpClientFactory(); // registers custom IForwarderHttpClientFactory\nbuilder.Services\n    .AddReverseProxy()\n    .ConfigureHttpClient((ctx, handler) =>\n    {\n        handler.MaxConnectionsPerServer = 100; // throws!\n    });\n// after — fold handler config into the custom factory\npublic class MyHttpClientFactory : ForwarderHttpClientFactory\n{\n    protected override SocketsHttpHandler CreateHandler(ForwarderHttpClientContext context)\n    {\n        var handler = base.CreateHandler(context);\n        handler.MaxConnectionsPerServer = 100;\n        return handler;\n    }\n}\n// Register only the custom factory — no ConfigureHttpClient call","handlingStrategy":"validation","validationCode":"// Before calling ConfigureHttpClient, check for existing custom factory\nvar existingFactory = builder.Services\n    .FirstOrDefault(s => s.ServiceType == typeof(IForwarderHttpClientFactory));\nif (existingFactory is not null && existingFactory.ImplementationType != typeof(ForwarderHttpClientFactory))\n    throw new InvalidOperationException(\"A custom IForwarderHttpClientFactory is already registered; cannot call ConfigureHttpClient\");","typeGuard":"// No type guard — this is a DI registration conflict, not a type-narrowing issue.","tryCatchPattern":"// Not applicable — fix the registration to use one approach, not both.","preventionTips":["Use either ConfigureHttpClient or a custom IForwarderHttpClientFactory, never both.","If you need both handler customization and factory-level control, fold handler config into the custom factory.","Review all AddSingleton<IForwarderHttpClientFactory> registrations across libraries that integrate with YARP."],"tags":["configuration","di","httpclient","registration-conflict","startup"],"backgroundTag":null,"analyzedSha":"bd11867bee7df522e7fd3effb08a9c85fd616908","analyzedAt":"2026-08-13T21:29:49.359Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}