LuckyPennySoftware/MediatR · error · InvalidOperationException
Could not create task for action method {actionForException.
Error message
Could not create task for action method {actionForException.MethodInfo}. What it means
Thrown at runtime by RequestExceptionActionProcessorBehavior when invoking an exception action's Execute method via reflection returns null. MediatR calls actionForException.MethodInfo.Invoke(...) and coalesces the result; Execute must return a Task, so null means the implementation violated that contract.
Source
Thrown at src/MediatR/Pipeline/RequestExceptionActionProcessorBehavior.cs:48
return await next(cancellationToken).ConfigureAwait(false);
}
catch (Exception exception)
{
var exceptionTypes = GetExceptionTypes(exception.GetType());
var actionsForException = exceptionTypes
.SelectMany(exceptionType => GetActionsForException(exceptionType, request))
.GroupBy(static actionForException => actionForException.Action.GetType())
.Select(static actionForException => actionForException.First())
.Select(static actionForException => (MethodInfo: GetMethodInfoForAction(actionForException.ExceptionType), actionForException.Action))
.ToList();
foreach (var actionForException in actionsForException)
{
try
{
await ((Task)(actionForException.MethodInfo.Invoke(actionForException.Action, new object[] { request, exception, cancellationToken })
?? throw new InvalidOperationException($"Could not create task for action method {actionForException.MethodInfo}."))).ConfigureAwait(false);
}
catch (TargetInvocationException invocationException) when (invocationException.InnerException != null)
{
// Unwrap invocation exception to throw the actual error
ExceptionDispatchInfo.Capture(invocationException.InnerException).Throw();
}
}
throw;
}
}
private static IEnumerable<Type> GetExceptionTypes(Type? exceptionType)
{
while (exceptionType != null && exceptionType != typeof(object))
{
yield return exceptionType;
exceptionType = exceptionType.BaseType;View on GitHub (pinned to 916ef1b3d6)
Solutions
- Ensure Execute always returns a non-null Task; for async methods use `async Task` and never return null/default; for sync use `return Task.CompletedTask;`.
- If the action has nothing to do, return Task.CompletedTask rather than null.
- Audit each IRequestExceptionAction implementation for unreachable-but-compiler-accepted null return paths.
Example fix
// before
public class MyAction : IRequestExceptionAction<MyRequest, MyException>
{
public Task Execute(MyRequest req, MyException ex, CancellationToken ct)
=> null; // throws at runtime
}
// after
public class MyAction : IRequestExceptionAction<MyRequest, MyException>
{
public Task Execute(MyRequest req, MyException ex, CancellationToken ct)
=> Task.CompletedTask;
} Defensive patterns
Strategy: validation
Validate before calling
// Cannot statically validate reflection results; ensure contract via code review.
// Unit test every IRequestExceptionAction to assert Execute returns non-null:
[Fact]
public async Task Execute_NeverReturnsNull()
{
var sut = new MyExceptionAction();
var task = sut.Execute(new MyRequest(), new MyException(), default);
Assert.NotNull(task);
await task;
} Try / catch
// Wrap mediator.Send in outer try/catch; this error is a contract violation
// in user code, not a transient condition. Catch to log and fail fast.
try { await mediator.Send(request, ct); }
catch (InvalidOperationException ex) when (ex.Message.StartsWith("Could not create task"))
{
logger.LogError(ex, "Exception action returned null Task");
throw;
} Prevention
- Never return null/default from IRequestExceptionAction.Execute; return Task.CompletedTask.
- Prefer async Task methods so the compiler enforces a returned Task.
When it happens
Trigger: An IRequestExceptionAction<TRequest, TException>.Execute implementation that returns null (e.g. an async method whose code path returns null or `await` is missing on a method returning null), or a sync method declared with a Task return type that does not return a Task instance.
Common situations: Hand-written Execute that does `return null;` or `return default;`; a method declared `public Task Execute(...)` with no return statement in a code path; miscompiled/dynamically-generated action types.
Related errors
- Could not find method {nameof(IRequestExceptionAction<TReque
- Did not return a Task from the exception handler.
- Could not find method {nameof(IRequestExceptionHandler<TRequ
- Open behavior type can not be null.
- The type "{openBehaviorType.Name}" must implement IPipelineB
AI-assisted analysis of LuckyPennySoftware/MediatR@916ef1b3d6 (2026-08-13).
Data as JSON: /api/errors/355d91271613f85d.
Report an issue: GitHub.