LuckyPennySoftware/MediatR · error · ArgumentException

{requestType.Name} does not implement IRequest

Error message

{requestType.Name} does not implement IRequest

What it means

The non-generic Send(object) overload inspects the runtime type's interfaces to find IRequest<> or IRequest before building a wrapper. If neither is implemented, the object is not a MediatR request at all, so ArgumentException is thrown naming the offending type.

Source

Thrown at src/MediatR/Mediator.cs:102

    public Task<object?> Send(object request, CancellationToken cancellationToken = default)
    {
        if (request == null)
        {
            throw new ArgumentNullException(nameof(request));
        }

        var handler = _requestHandlers.GetOrAdd(request.GetType(), static requestType =>
        {
            Type wrapperType;

            var requestInterfaceType = requestType.GetInterfaces().FirstOrDefault(static i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IRequest<>));
            if (requestInterfaceType is null)
            {
                requestInterfaceType = requestType.GetInterfaces().FirstOrDefault(static i => i == typeof(IRequest));
                if (requestInterfaceType is null)
                {
                    throw new ArgumentException($"{requestType.Name} does not implement {nameof(IRequest)}", nameof(request));
                }

                wrapperType = typeof(RequestHandlerWrapperImpl<>).MakeGenericType(requestType);
            }
            else
            {
                var responseType = requestInterfaceType.GetGenericArguments()[0];
                wrapperType = typeof(RequestHandlerWrapperImpl<,>).MakeGenericType(requestType, responseType);
            }

            var wrapper = Activator.CreateInstance(wrapperType) ?? throw new InvalidOperationException($"Could not create wrapper for type {requestType}");
            return (RequestHandlerBase)wrapper;
        });

        // call via dynamic dispatch to avoid calling through reflection for performance reasons
        return handler.Handle(request, _serviceProvider, cancellationToken);
    }

View on GitHub (pinned to 916ef1b3d6)

Solutions

  1. Mark the request type with `public record Foo : IRequest<Bar>` (or IRequest for unit).
  2. If the object is a notification, call Publish, not Send.
  3. Where possible, use the generic Send<TResponse>(IRequest<TResponse>) overload so the contract is checked at compile time.

Example fix

// before
public class DoThing { public int Id; }
mediator.Send(new DoThing()); // ArgumentException
// after
public record DoThing(int Id) : IRequest<int>;
mediator.Send(new DoThing(1));
Defensive patterns

Strategy: type-guard

Validate before calling

var reqInterfaces = request.GetType().GetInterfaces();
bool isRequest = reqInterfaces.Any(i => i == typeof(IRequest))
    || reqInterfaces.Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IRequest<>));
if (!isRequest) throw new ArgumentException($"{request.GetType().Name} is not a MediatR request.", nameof(request));

Type guard

static bool IsMediatRRequest(object o) =>
    o.GetType().GetInterfaces().Any(i => i == typeof(IRequest)
        || (i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IRequest<>)));

Prevention

When it happens

Trigger: Calling mediator.Send(someObject) where someObject's runtime type does not implement IRequest or IRequest<TResponse> — e.g. a DTO, a primitive wrapped in object, or a command that was never marked with the IRequest interface.

Common situations: Publishing/sending through a non-generic boundary (messaging, reflection, dynamic dispatch) and passing a payload type that forgot to implement IRequest; sending a notification through Send instead of Publish; version mismatch where the request interface was renamed/removed.

Related errors


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