ThreeMammals/Ocelot · error · ArgumentOutOfRangeException

It is not a delegating handler

Error message

It is not a delegating handler

What it means

This is a validation guard inside the AddDelegatingHandler fluent method of IOcelotBuilder. The method registers a message-handler type as a transient DelegatingHandler service for Ocelot's HttpClient pipeline; before registering it checks that the supplied delegateType is actually assignable to DelegatingHandler. The input at fault is the caller-supplied delegateType argument: passing any type that does not derive from DelegatingHandler (e.g. a plain HttpClientHandler, an IHttpMessageHandler implementation that is not a DelegatingHandler, or an unrelated type) makes the generic constraint check fail and the error is thrown at DI-registration time, during Ocelot service configuration, before any request is handled.

Solutions

  1. Pass a Type that derives from System.Net.Http.DelegatingHandler, e.g. typeof(MyDelegatingHandler).
  2. If registering a delegate, use the AddDelegatingHandler(Func<DelegatingHandler>, bool) overload instead of the type-based overload.
  3. Verify with typeof(DelegatingHandler).IsAssignableFrom(delegateType) before calling AddDelegatingHandler.
  4. Ensure generics/assembly loading (e.g. reflection-based plugin loading) resolve to the DelegatingHandler subclass, not a base handler type such as HttpMessageHandler.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at src/DependencyInjection/OcelotBuilder.cs:278 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of ThreeMammals/Ocelot@d1f22d9304 (2026-09-12). Data as JSON: /api/errors/c6c4eda7f831087f. Report an issue: GitHub.

Appendix: source

Thrown at src/DependencyInjection/OcelotBuilder.cs:278

            return new DelegateInvokingLoadBalancerCreator<TLoadBalancer>(Create);
        }

        Services.AddSingleton<ILoadBalancerCreator>(implementationFactory);
        return this;
    }

    /// <summary>
    /// Adds a <see cref="DelegatingHandler"/> of the <paramref name="delegateType"/> type as a transient service, with the <paramref name="global"/> option to make the handler globally available.
    /// </summary>
    /// <param name="delegateType">The type of a <see cref="DelegatingHandler"/> to be registered.</param>
    /// <param name="global">True if the handler should be globally available.</param>
    /// <returns>A reference to the same <see cref="IOcelotBuilder"/> object.</returns>
    /// <exception cref="ArgumentOutOfRangeException">Generates an exception if the <paramref name="delegateType"/> type does not inherit from the <see cref="DelegatingHandler"/>.</exception>
    public IOcelotBuilder AddDelegatingHandler(Type delegateType, bool global = false)
    {
        if (!typeof(DelegatingHandler).IsAssignableFrom(delegateType))
        {
            throw new ArgumentOutOfRangeException(nameof(delegateType), delegateType.Name, "It is not a delegating handler");
        }

        if (global)
        {
            Services.AddTransient(delegateType);
            Services.AddTransient(provider =>
            {
                var service = provider.GetService(delegateType) as DelegatingHandler;
                return new GlobalDelegatingHandler(service);
            });
        }
        else
        {
            Services.AddTransient(typeof(DelegatingHandler), delegateType);
        }

        return this;
    }

View on GitHub (pinned to d1f22d9304)