LuckyPennySoftware/MediatR · error · InvalidOperationException

{implementationType.Name} must implement {typeof(IStreamPipe

Error message

{implementationType.Name} must implement {typeof(IStreamPipelineBehavior<,>).FullName}

What it means

AddStreamBehavior(Type, ServiceLifetime) mirrors AddBehavior for the streaming pipeline: it calls FindInterfacesThatClose(IStreamPipelineBehavior<,>) and throws InvalidOperationException when none are found, ensuring only valid closed stream behaviors are registered.

Source

Thrown at src/MediatR/MicrosoftExtensionsDI/MediatrServiceConfiguration.cs:307

    /// <typeparam name="TImplementationType">Closed stream behavior implementation type</typeparam>
    /// <param name="serviceLifetime">Optional service lifetime, defaults to <see cref="ServiceLifetime.Transient"/>.</param>
    /// <returns>This</returns>
    public MediatRServiceConfiguration AddStreamBehavior<TImplementationType>(ServiceLifetime serviceLifetime = ServiceLifetime.Transient)
        => AddStreamBehavior(typeof(TImplementationType), serviceLifetime);
    
    /// <summary>
    /// Register a closed stream behavior type against all <see cref="IStreamPipelineBehavior{TRequest,TResponse}"/> implementations
    /// </summary>
    /// <param name="implementationType">Closed stream behavior implementation type</param>
    /// <param name="serviceLifetime">Optional service lifetime, defaults to <see cref="ServiceLifetime.Transient"/>.</param>
    /// <returns>This</returns>
    public MediatRServiceConfiguration AddStreamBehavior(Type implementationType, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)
    {
        var implementedGenericInterfaces = implementationType.FindInterfacesThatClose(typeof(IStreamPipelineBehavior<,>)).ToList();

        if (implementedGenericInterfaces.Count == 0)
        {
            throw new InvalidOperationException($"{implementationType.Name} must implement {typeof(IStreamPipelineBehavior<,>).FullName}");
        }

        foreach (var implementedBehaviorType in implementedGenericInterfaces)
        {
            StreamBehaviorsToRegister.Add(new ServiceDescriptor(implementedBehaviorType, implementationType, serviceLifetime));
        }

        return this;
    }
    
    /// <summary>
    /// Registers an open stream behavior type against the <see cref="IStreamPipelineBehavior{TRequest,TResponse}"/> open generic interface type
    /// </summary>
    /// <param name="openBehaviorType">An open generic stream behavior type</param>
    /// <param name="serviceLifetime">Optional service lifetime, defaults to <see cref="ServiceLifetime.Transient"/>.</param>
    /// <returns>This</returns>
    public MediatRServiceConfiguration AddOpenStreamBehavior(Type openBehaviorType, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)
    {

View on GitHub (pinned to 916ef1b3d6)

Solutions

  1. Ensure the type implements IStreamPipelineBehavior<TRequest, TResponse>.
  2. For request (non-stream) behaviors use AddBehavior / IPipelineBehavior<,>.
  3. For open-generic stream behaviors use AddOpenStreamBehavior(typeof(Foo<,>)).

Example fix

// before
// RequestLogging<TReq,TResp> implements IPipelineBehavior<,>
configuration.AddStreamBehavior(typeof(RequestLogging<,>));
// after
configuration.AddBehavior(typeof(RequestLogging<,>));
Defensive patterns

Strategy: validation

Validate before calling

var closes = implementationType.FindInterfacesThatClose(typeof(IStreamPipelineBehavior<,>)).ToList();
if (closes.Count == 0)
    throw new InvalidOperationException($"{implementationType.Name} is not a closed IStreamPipelineBehavior<,>.");

Type guard

static bool IsClosedStreamBehavior(Type t) =>
    t.FindInterfacesThatClose(typeof(IStreamPipelineBehavior<,>)).Any();

Prevention

When it happens

Trigger: Passing a Type to AddStreamBehavior that implements IPipelineBehavior<,> (request pipeline) instead of IStreamPipelineBehavior<,>, or implements neither.

Common situations: Confusing request vs stream pipeline behaviors; registering an open generic via AddStreamBehavior instead of AddOpenStreamBehavior; registering a non-behavior class.

Related errors


AI-assisted analysis of LuckyPennySoftware/MediatR@916ef1b3d6 (2026-08-13). Data as JSON: /api/errors/9a9fe8c68192417a. Report an issue: GitHub.