elsa-workflows/elsa-core · error · InvalidOperationException
There is no handler to handle the
Error message
There is no handler to handle the {commandType.FullName} command What it means
Elsa.Mediator's command pipeline resolves exactly one ICommandHandler<TCommand,TResult> from DI for each command being sent. This error is thrown when zero handlers matching the command's type and expected result type are found among the registered ICommandHandler services. It means the command was dispatched but no handler was ever registered in the dependency injection container.
Solutions
- Register a handler for the command: services.AddCommandHandler<MyCommandHandler>() (or AddHandlersFrom<MarkerTypeInHandlersAssembly>()).
- Verify the handler implements exactly ICommandHandler<TCommand, TResult> with TCommand equal to the sent command's type and TResult equal to the expected ResultType of the Send call.
- Confirm the mediator and the handler are registered on the same IServiceCollection / service provider instance that is resolving services.
- Check that assembly scanning includes the assembly containing the handler and that the handler is public (non-abstract).
- If the command should not require a handler, ensure you are not sending it accidentally (e.g. wrong message type passed to SendAsync instead of PublishAsync).
Example fix
// before services.AddMediator(); await mediator.SendAsync(new CreateOrderCommand(order)); // throws: no handler // after services.AddMediator(); services.AddCommandHandler<CreateOrderCommandHandler>(); // implements ICommandHandler<CreateOrderCommand, Order>
Defensive patterns
Strategy: validation
Validate before calling
// Before sending, verify a handler is registered:
var handlerType = typeof(ICommandHandler<,>).MakeGenericType(command.GetType(), typeof(TResult));
var hasHandler = serviceProvider.GetServices<Elsa.Mediator.Contracts.ICommandHandler>()
.Any(h => handlerType.IsInstanceOfType(h));
if (!hasHandler)
throw new InvalidOperationException($"No handler registered for {command.GetType().Name}; call AddCommandHandler<...>() first."); Type guard
static bool HasHandler<TCommand, TResult>(IServiceProvider sp) =>
sp.GetServices<Elsa.Mediator.Contracts.ICommandHandler>().Any(h =>
h is Elsa.Mediator.Contracts.ICommandHandler<TCommand, TResult>); Try / catch
try
{
await mediator.SendAsync(command, cancellationToken);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("There is no handler to handle"))
{
logger.LogError(ex, "Missing handler for {Command}", command.GetType().Name);
throw;
} Prevention
- Use assembly scanning (AddHandlersFrom<TMarker>()) so new handlers register automatically.
- Pair every command type with its handler in the same feature/dependency-registration file.
- Write a startup test asserting every ICommand implementation has exactly one registered handler.
- Keep the handler's TResult identical to the generic argument used in SendAsync.
When it happens
Trigger: Calling IMediator.SendAsync (or ICommandSender) with a command type for which no class implementing ICommandHandler<ThatCommand, TResult> was registered in the service provider; registering the handler with a mismatched TResult so handlerType.IsInstanceOfType fails; forgetting to call AddCommandHandler<THandler>() / AddHandlersFrom<TAssembly>() during host configuration.
Common situations: Developers add a new command and handler but forget DI registration; handler registered for the wrong result type (e.g. ICommandHandler<MyCommand, Unit> vs ICommandHandler<MyCommand, MyResult>); handler registered in a different service collection than the one the mediator resolves from (test host vs app host); assembly scanning misses the handler's namespace; renaming a handler type breaks an explicit registration.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- Multiple handlers were found to handle the
- There is no handler to handle the
- Multiple handlers were found to handle the
- Multiple Invoke methods were found. Use either Invoke or…
- No Invoke methods were found. Use either Invoke or…
AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13).
Data as JSON: /api/errors/3e523b39a0049604.
Report an issue: GitHub.
Appendix: source
Thrown at src/common/Elsa.Mediator/Middleware/Command/Components/CommandHandlerInvokerMiddleware.cs:30
/// </summary>
[UsedImplicitly]
public class CommandHandlerInvokerMiddleware(CommandMiddlewareDelegate next) : ICommandMiddleware
{
/// <inheritdoc />
[UnconditionalSuppressMessage("Trimming", "IL2060:Call to MakeGenericMethod can not be statically analyzed", Justification = "The result type is determined at runtime from command types and handlers are registered in DI.")]
public async ValueTask InvokeAsync(CommandContext context)
{
// Find all handlers for the specified command.
var command = context.Command;
var commandType = command.GetType();
var resultType = context.ResultType;
var handlerType = typeof(ICommandHandler<,>).MakeGenericType(commandType, resultType);
var serviceProvider = context.ServiceProvider;
var commandHandlers = serviceProvider.GetServices<ICommandHandler>();
var handlers = commandHandlers.DistinctBy(x => x.GetType()).Where(x => handlerType.IsInstanceOfType(x)).ToArray();
if (handlers.Length == 0)
throw new InvalidOperationException($"There is no handler to handle the {commandType.FullName} command");
if (handlers.Length > 1)
throw new InvalidOperationException($"Multiple handlers were found to handle the {commandType.FullName} command");
var handler = handlers.First();
var strategyContext = new CommandStrategyContext(context, handler, serviceProvider, context.CancellationToken);
var strategy = context.CommandStrategy;
var executeMethod = strategy.GetType().GetMethod(nameof(ICommandStrategy.ExecuteAsync))!;
var executeMethodWithReturnType = executeMethod.MakeGenericMethod(resultType);
// Execute command.
var task = (Task)executeMethodWithReturnType.Invoke(strategy, [strategyContext])!;
// Wait for completion.
await task;
// Get the result of the task.
var taskWithReturnType = typeof(Task<>).MakeGenericType(resultType);View on GitHub (pinned to fe9217bdfa)