LuckyPennySoftware/MediatR · error · InvalidOperationException

{openBehaviorType.Name} must implement {typeof(IRequestPrePr

Error message

{openBehaviorType.Name} must implement {typeof(IRequestPreProcessor<>).FullName}

What it means

Thrown by AddOpenRequestPreProcessor after the generic check passes: the type is generic but none of its implemented generic interfaces equal IRequestPreProcessor<>. MediatR filters GetInterfaces() to generic definitions and requires at least one match to register.

Source

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

    /// <summary>
    /// Registers an open request pre processor type against the <see cref="IRequestPreProcessor{TRequest}"/> open generic interface type
    /// </summary>
    /// <param name="openBehaviorType">An open generic request pre processor type</param>
    /// <param name="serviceLifetime">Optional service lifetime, defaults to <see cref="ServiceLifetime.Transient"/>.</param>
    /// <returns>This</returns>
    public MediatRServiceConfiguration AddOpenRequestPreProcessor(Type openBehaviorType, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)
    {
        if (!openBehaviorType.IsGenericType)
        {
            throw new InvalidOperationException($"{openBehaviorType.Name} must be generic");
        }

        var implementedGenericInterfaces = openBehaviorType.GetInterfaces().Where(i => i.IsGenericType).Select(i => i.GetGenericTypeDefinition());
        var implementedOpenBehaviorInterfaces = new HashSet<Type>(implementedGenericInterfaces.Where(i => i == typeof(IRequestPreProcessor<>)));

        if (implementedOpenBehaviorInterfaces.Count == 0)
        {
            throw new InvalidOperationException($"{openBehaviorType.Name} must implement {typeof(IRequestPreProcessor<>).FullName}");
        }

        foreach (var openBehaviorInterface in implementedOpenBehaviorInterfaces)
        {
            RequestPreProcessorsToRegister.Add(new ServiceDescriptor(openBehaviorInterface, openBehaviorType, serviceLifetime));
        }

        return this;
    }
    
    /// <summary>
    /// Register a closed request post processor type
    /// </summary>
    /// <typeparam name="TServiceType">Closed request post processor interface type</typeparam>
    /// <typeparam name="TImplementationType">Closed request post processor implementation type</typeparam>
    /// <param name="serviceLifetime">Optional service lifetime, defaults to <see cref="ServiceLifetime.Transient"/>.</param>
    /// <returns>This</returns>
    public MediatRServiceConfiguration AddRequestPostProcessor<TServiceType, TImplementationType>(ServiceLifetime serviceLifetime = ServiceLifetime.Transient)

View on GitHub (pinned to 916ef1b3d6)

Solutions

  1. Implement the open interface on the generic class: class MyProcessor<TRequest> : IRequestPreProcessor<TRequest>.
  2. If the type actually implements IRequestPostProcessor<,> or IPipelineBehavior<,>, move the registration to AddOpenRequestPostProcessor / AddOpenBehavior respectively.
  3. Confirm the open generic declares the interface with the matching open type parameter, not a concrete one.

Example fix

// before
public class MyProcessor<TRequest, TResponse>
    : IRequestPostProcessor<TRequest, TResponse> { ... }
cfg.AddOpenRequestPreProcessor(typeof(MyProcessor<,>));

// after
cfg.AddOpenRequestPostProcessor(typeof(MyProcessor<,>));
Defensive patterns

Strategy: validation

Validate before calling

static bool ImplementsOpenPreProcessor(Type t) =>
    t.IsGenericType &&
    t.GetInterfaces()
        .Where(i => i.IsGenericType)
        .Select(i => i.GetGenericTypeDefinition())
        .Any(i => i == typeof(IRequestPreProcessor<>));

if (ImplementsOpenPreProcessor(typeof(MyProcessor<>)))
    cfg.AddOpenRequestPreProcessor(typeof(MyProcessor<>));

Type guard

static bool IsOpenRequestPreProcessor(Type t) =>
    t.IsGenericType &&
    t.GetInterfaces()
        .Where(i => i.IsGenericType)
        .Select(i => i.GetGenericTypeDefinition())
        .Contains(typeof(IRequestPreProcessor<>));

Prevention

When it happens

Trigger: Registering typeof(MyGenericBehavior<>) where the class is generic but implements IRequestPostProcessor<,>, IPipelineBehavior<,>, or no processor interface.

Common situations: Open generic class that implements a different MediatR interface; renamed interface; wrong arity chosen (pre-processor is single-arity IRequestPreProcessor<TRequest>).

Related errors


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