{"record":{"id":"f3ac426eb7bc1d13","repo":"elsa-workflows/elsa-core","slug":"no-invoke-methods-were-found-use-either-invoke-or","errorCode":null,"errorMessage":"No Invoke methods were found. Use either Invoke or InvokeAsync","messagePattern":"No Invoke methods were found\\. Use either Invoke or InvokeAsync","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/common/Elsa.Mediator/Middleware/MiddlewareHelpers.cs","lineNumber":28,"sourceCode":"    /// <summary>\n    /// Gets the Invoke or InvokeAsync method from the middleware type.\n    /// </summary>\n    /// <param name=\"middleware\">The middleware type.</param>\n    /// <returns>The Invoke or InvokeAsync method.</returns>\n    /// <exception cref=\"InvalidOperationException\">Thrown when the Invoke or InvokeAsync method cannot be found or the return type is not Task or ValueTask.</exception>\n    public static MethodInfo GetInvokeMethod(Type middleware)\n    {\n        const string invokeMethodName = \"Invoke\";\n        const string invokeAsyncMethodName = \"InvokeAsync\";\n        var methods = middleware.GetMethods(BindingFlags.Instance | BindingFlags.Public);\n        var invokeMethods = methods.Where(m => string.Equals(m.Name, invokeMethodName, StringComparison.Ordinal) || string.Equals(m.Name, invokeAsyncMethodName, StringComparison.Ordinal)).ToArray();\n\n        switch (invokeMethods.Length)\n        {\n            case > 1:\n                throw new InvalidOperationException(\"Multiple Invoke methods were found. Use either Invoke or InvokeAsync.\");\n            case 0:\n                throw new InvalidOperationException(\"No Invoke methods were found. Use either Invoke or InvokeAsync\");\n        }\n\n        var methodInfo = invokeMethods[0];\n\n        if (!typeof(Task).IsAssignableFrom(methodInfo.ReturnType) && !typeof(ValueTask).IsAssignableFrom(methodInfo.ReturnType))\n            throw new InvalidOperationException($\"The {methodInfo.Name} method must return Task or ValueTask\");\n\n        return methodInfo;\n    }\n}","sourceCodeStart":10,"sourceCodeEnd":38,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/common/Elsa.Mediator/Middleware/MiddlewareHelpers.cs#L10-L38","documentation":"MiddlewareHelpers.GetInvokeMethod requires every middleware to expose a public instance method named exactly Invoke or InvokeAsync, which the pipeline invokes via reflection. This error is thrown when no such method exists on the middleware type, so the mediator cannot discover its entry point.","triggerScenarios":"Registering a middleware class that does not implement the Invoke/InvokeAsync convention and does not implement IMiddleware/ICommandMiddleware; renaming the method (e.g. to HandleAsync or InvokeInternal); middleware defined with a static Invoke method (statics are excluded by BindingFlags.Instance); method made private/protected; wrong type registered as middleware (e.g. a handler or service class by mistake).","commonSituations":"Writing a custom pipeline middleware from scratch and missing the convention; a typo like InvokeeAsync or InvokeAsnyc; refactoring that renamed the method without updating the pipeline contract; passing the wrong type into middleware registration during DI setup.","solutions":["Add a public instance method named InvokeAsync (or Invoke) accepting the pipeline context and next delegate, matching the IMiddleware contract for your pipeline.","Implement the proper interface (IMiddleware, ICommandMiddleware, etc.) to get the method signature right.","Make the method instance-level and public (not static, not private).","Verify you registered the intended middleware type, not an unrelated class, in the pipeline configuration."],"exampleFix":"// before\npublic class MyMiddleware : ICommandMiddleware\n{\n    public ValueTask HandleAsync(CommandContext context, CommandMiddlewareDelegate next) => next(context); // wrong name\n}\n\n// after\npublic class MyMiddleware : ICommandMiddleware\n{\n    public ValueTask InvokeAsync(CommandContext context, CommandMiddlewareDelegate next) => next(context);","handlingStrategy":"validation","validationCode":"// Before registering middleware, ensure a public instance Invoke/InvokeAsync exists:\nvar hasInvoke = middlewareType.GetMethods(BindingFlags.Instance | BindingFlags.Public)\n    .Any(m => m.Name is \"Invoke\" or \"InvokeAsync\");\nif (!hasInvoke)\n    throw new InvalidOperationException($\"{middlewareType.Name} is missing a public Invoke/InvokeAsync method.\");","typeGuard":"static bool IsMiddleware(Type t) =>\n    typeof(Elsa.Mediator.Contracts.IMiddleware).IsAssignableFrom(t) &&\n    t.GetMethods(BindingFlags.Instance | BindingFlags.Public)\n     .Any(m => m.Name is \"Invoke\" or \"InvokeAsync\");","tryCatchPattern":"try\n{\n    pipeline.AddMiddleware(typeof(MyMiddleware));\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"No Invoke methods were found\"))\n{\n    logger.LogError(ex, \"{Type} does not follow the middleware Invoke convention\", typeof(MyMiddleware).Name);\n    throw;\n}","preventionTips":["Always implement the middleware interface so the compiler enforces the InvokeAsync signature.","Never rename the entry-point method; refactor inside it instead.","Keep the method public and instance-level (not static).","Unit-test middleware registration for every custom middleware class."],"tags":["mediator","middleware","reflection","pipeline"],"backgroundTag":"method-not-implemented","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}