{"record":{"id":"355d91271613f85d","repo":"LuckyPennySoftware/MediatR","slug":"could-not-create-task-for-action-method-actionfor","errorCode":null,"errorMessage":"Could not create task for action method {actionForException.MethodInfo}.","messagePattern":"Could not create task for action method (.+?)\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/MediatR/Pipeline/RequestExceptionActionProcessorBehavior.cs","lineNumber":48,"sourceCode":"            return await next(cancellationToken).ConfigureAwait(false);\n        }\n        catch (Exception exception)\n        {\n            var exceptionTypes = GetExceptionTypes(exception.GetType());\n\n            var actionsForException = exceptionTypes\n                .SelectMany(exceptionType => GetActionsForException(exceptionType, request))\n                .GroupBy(static actionForException => actionForException.Action.GetType())\n                .Select(static actionForException => actionForException.First())\n                .Select(static actionForException => (MethodInfo: GetMethodInfoForAction(actionForException.ExceptionType), actionForException.Action))\n                .ToList();\n\n            foreach (var actionForException in actionsForException)\n            {\n                try\n                {\n                    await ((Task)(actionForException.MethodInfo.Invoke(actionForException.Action, new object[] { request, exception, cancellationToken })\n                                  ?? throw new InvalidOperationException($\"Could not create task for action method {actionForException.MethodInfo}.\"))).ConfigureAwait(false);\n                }\n                catch (TargetInvocationException invocationException) when (invocationException.InnerException != null)\n                {\n                    // Unwrap invocation exception to throw the actual error\n                    ExceptionDispatchInfo.Capture(invocationException.InnerException).Throw();\n                }\n            }\n\n            throw;\n        }\n    }\n\n    private static IEnumerable<Type> GetExceptionTypes(Type? exceptionType)\n    {\n        while (exceptionType != null && exceptionType != typeof(object))\n        {\n            yield return exceptionType;\n            exceptionType = exceptionType.BaseType;","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/LuckyPennySoftware/MediatR/blob/916ef1b3d68ccdc96db8f914eaf1b32fc7db52c5/src/MediatR/Pipeline/RequestExceptionActionProcessorBehavior.cs#L30-L66","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\npublic class MyAction : IRequestExceptionAction<MyRequest, MyException>\n{\n    public Task Execute(MyRequest req, MyException ex, CancellationToken ct)\n        => null; // throws at runtime\n}\n\n// after\npublic class MyAction : IRequestExceptionAction<MyRequest, MyException>\n{\n    public Task Execute(MyRequest req, MyException ex, CancellationToken ct)\n        => Task.CompletedTask;\n}","handlingStrategy":"validation","validationCode":"// Cannot statically validate reflection results; ensure contract via code review.\n// Unit test every IRequestExceptionAction to assert Execute returns non-null:\n[Fact]\npublic async Task Execute_NeverReturnsNull()\n{\n    var sut = new MyExceptionAction();\n    var task = sut.Execute(new MyRequest(), new MyException(), default);\n    Assert.NotNull(task);\n    await task;\n}","typeGuard":null,"tryCatchPattern":"// Wrap mediator.Send in outer try/catch; this error is a contract violation\n// in user code, not a transient condition. Catch to log and fail fast.\ntry { await mediator.Send(request, ct); }\ncatch (InvalidOperationException ex) when (ex.Message.StartsWith(\"Could not create task\"))\n{\n    logger.LogError(ex, \"Exception action returned null Task\");\n    throw;\n}","preventionTips":["Never return null/default from IRequestExceptionAction.Execute; return Task.CompletedTask.","Prefer async Task methods so the compiler enforces a returned Task."],"tags":["pipeline","exception-action","reflection","runtime"],"backgroundTag":null,"analyzedSha":"916ef1b3d68ccdc96db8f914eaf1b32fc7db52c5","analyzedAt":"2026-08-13T17:57:04.476Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}