LuckyPennySoftware/MediatR · error · InvalidOperationException

Did not return a Task from the exception handler.

Error message

Did not return a Task from the exception handler.

What it means

Thrown at runtime by RequestExceptionProcessorBehavior when an exception handler's Handle method (invoked via reflection) returns null instead of a Task. The handler contract is IRequestExceptionHandler<TRequest,TResponse,TException>.Handle returning Task and setting state.Handled; null violates it.

Source

Thrown at src/MediatR/Pipeline/RequestExceptionProcessorBehavior.cs:50

        catch (Exception exception)
        {
            var state = new RequestExceptionHandlerState<TResponse>();

            var exceptionTypes = GetExceptionTypes(exception.GetType());

            var handlersForException = exceptionTypes
                .SelectMany(exceptionType => GetHandlersForException(exceptionType, request))
                .GroupBy(static handlerForException => handlerForException.Handler.GetType())
                .Select(static handlerForException => handlerForException.First())
                .Select(static handlerForException => (MethodInfo: GetMethodInfoForHandler(handlerForException.ExceptionType), handlerForException.Handler))
                .ToList();

            foreach (var handlerForException in handlersForException)
            {
                try
                {
                    await ((Task) (handlerForException.MethodInfo.Invoke(handlerForException.Handler, new object[] { request, exception, state, cancellationToken })
                                   ?? throw new InvalidOperationException("Did not return a Task from the exception handler."))).ConfigureAwait(false);
                }
                catch (TargetInvocationException invocationException) when (invocationException.InnerException != null)
                {
                    // Unwrap invocation exception to throw the actual error
                    ExceptionDispatchInfo.Capture(invocationException.InnerException).Throw();
                }

                if (state.Handled)
                {
                    break;
                }
            }

            if (!state.Handled)
            {
                throw;
            }

View on GitHub (pinned to 916ef1b3d6)

Solutions

  1. Make Handle always return a non-null Task; use `async Task` and never return null, or `return Task.CompletedTask;` for sync.
  2. If you intend not to handle the exception, set state.Handled = false and return Task.CompletedTask instead of null.
  3. Add a unit test asserting Handle returns non-null for all code paths.

Example fix

// before
public class MyHandler : IRequestExceptionHandler<MyReq, MyResp, MyException>
{
    public Task Handle(MyReq req, MyException ex,
        RequestExceptionHandlerState<MyResp> state, CancellationToken ct)
        => null;
}

// after
public class MyHandler : IRequestExceptionHandler<MyReq, MyResp, MyException>
{
    public async Task Handle(MyReq req, MyException ex,
        RequestExceptionHandlerState<MyResp> state, CancellationToken ct)
    {
        state.SetHandled(new MyResp());
        await Task.CompletedTask;
    }
}
Defensive patterns

Strategy: validation

Validate before calling

// Unit test that every IRequestExceptionHandler.Handle returns a non-null Task
[Fact]
public async Task Handle_ReturnsTask()
{
    var sut = new MyExceptionHandler();
    var state = new RequestExceptionHandlerState<MyResponse>();
    var task = sut.Handle(new MyRequest(), new MyException(), state, default);
    Assert.NotNull(task);
    await task;
}

Try / catch

try { await mediator.Send(request, ct); }
catch (InvalidOperationException ex) when (ex.Message == "Did not return a Task from the exception handler.")
{
    logger.LogError(ex, "Exception handler returned null Task");
    throw;
}

Prevention

When it happens

Trigger: An IRequestExceptionHandler implementation whose Handle returns null (e.g. `return null;`, `return default;`, or an async method whose code path returns null).

Common situations: Custom exception handler with a missed return path; copy-pasting a void-style handler into a Task-returning signature; dynamic/generated handler that misbehaves.

Related errors


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