Troubleshooting
This page maps the exceptions and surprising behaviors LiteBus produces to their cause and fix. Each entry names the exception type, where it is thrown, why, and what to change. Use it as a lookup when a message fails to mediate or a registration throws at startup. The behaviors here are grounded in The Handler Pipeline.
InvalidOperationException (Transactional Writer Requires Active Transaction)
Message contains requires an active PostgreSQL transaction.
Cause: ITransactionalInbox or ITransactionalOutbox was used with EnableAmbientTransactionProvider() (default RequireActiveTransaction), but no transaction was active in IPostgreSqlTransactionProvider.
Fix:
- Open connection and
BeginTransactionAsyncat unit-of-work start; implementTryGetCurrenton your scoped provider. - Confirm the handler injects
ITransactionalOutbox, notIOutbox.
See Transactional messaging writes and the troubleshooting section there.
NoHandlerFoundException
Message: No handler found for message type '<Type>'.
Thrown by the mediator when it cannot resolve a descriptor for the message: the message type, or a handler for it, was never registered. For events it is thrown only when EventMediationSettings.ThrowIfNoHandlerFound is true; otherwise a published event with no handler returns silently.
Fix:
- Register the handler's assembly:
module.RegisterFromAssembly(typeof(SomeHandler).Assembly), or register the handler explicitly. - Confirm the message implements the right marker (
ICommand,IQuery<T>,IEvent) for the module you registered. - In
WebApplicationFactorytests, register LiteBus modules inside each factory'sConfigureTestServicesso handler discovery uses that factory's ownIMessageRegistry. See Testing LiteBus.
MultipleHandlerFoundException
Message: <Type> has <n> handlers registered.
Thrown by the single-handler strategies for commands and queries when more than one main handler matches. Commands and queries must resolve to exactly one main handler. This is checked before any handler runs.
Fix:
- Remove the duplicate handler, or merge the two into one.
- Check you did not register the same assembly twice, or register a handler both explicitly and by assembly scan.
- If you intended fan-out to multiple handlers, the message should be an event, not a command or query. Events broadcast to all matching handlers. See Event Module.
UnsupportedOpenGenericHandlerException
Message: Open generic handler type '<Type>' declares <n> generic parameters. LiteBus supports open generic handlers with exactly one generic parameter.
Thrown at registration when an open generic handler declares more than one type parameter, such as MyHandler<TCommand, TResult>. LiteBus closes open generic handlers only when they have exactly one type parameter.
Fix:
- Reduce the handler to a single type parameter, for example
ICommandPreHandler<T>. - If you need the result type, read it inside the handler rather than as a second type parameter, or use a concrete handler. See Open Generic Handlers.
LiteBusExecutionAbortedException
Thrown internally when a handler calls AmbientExecutionContext.Current.Abort(...). In a command or query pipeline the single-handler strategy catches it and ends mediation cleanly, so you should not see it escape. You will see it escape if you call Abort inside an event pipeline, where the broadcast strategy treats it as an ordinary exception and routes it to error-handlers (which rethrow if none are registered).
Fix:
- Use
Abortonly in command and query pipelines, typically a pre-handler returning a cached result. - To skip event handlers, filter them with tags or a predicate instead. See Handler Filtering.
InvalidOperationException When Aborting a Result Message
Thrown when you call Abort() without a value on a result-returning command or query. The caller is owed a result, so an abort must supply one.
Fix: pass the value, Abort(result). For a void command (ICommand), Abort() with no argument is correct. See Execution Context.
LB1004: Command with Result Scheduled to Inbox
Diagnostic: LB1004 (analyzer error) or runtime failure when IInbox.AcceptAsync is invoked with a command that implements ICommand<TResult>. The inbox discards handler results when it replays a message later, so only result-less ICommand types can be stored.
Fix: store a result-less command, and query for the outcome separately when a caller needs it. Reference LiteBus.Analyzers so LB1004 catches invalid inbox writes at compile time. See Inbox and Analyzers.
Swallowed Exception: An Error-Handler That Does Not Rethrow
Behavior, not an exception. When a stage throws and at least one error-handler is registered, the error-handlers run and the exception is considered handled unless one rethrows. An error-handler that only logs silently swallows the failure, and a result-returning caller then receives whatever partial result existed, possibly null.
Fix: rethrow from the error-handler (throw exception;) unless you intend to swallow. See The Handler Pipeline.
Event Handler Did Not Run
Behavior. A published event ran no handler. Causes:
- No handler is registered for the event type, and
ThrowIfNoHandlerFoundisfalse, so the publish returned silently. Set it totruein tests to make this fail loudly. - A tag or predicate filtered the handler out. Check the tags passed to
PublishAsyncagainst the handler's[HandlerTag]. See Handler Filtering. - A pre-handler threw before the main handlers ran, so the broadcast stopped. Check error-handler behavior above.
Handlers Ran in an Unexpected Order
Behavior. Within a stage, handlers run in ascending [HandlerPriority] (default 0). Across the onion, global pre-handlers run before specific ones and specific post-handlers run before global ones. For events, priority groups and within-group execution follow the concurrency switches on EventMediationSettings.Execution; parallel execution makes order non-deterministic.
Fix: set explicit priorities, or switch event execution to Sequential. See Handler Priority.
InvalidOperationException from Inbox or Outbox Hosting
Thrown when the generic host builds InboxProcessorBackgroundService or OutboxProcessorBackgroundService and DI cannot resolve required dependencies. Common causes:
EnableInboxProcessor()orEnableOutboxProcessor()is set but noIInboxDispatcherorIOutboxDispatcheris registered (UseInProcessDispatchor a broker-specificUse*Dispatch).- Storage is missing (
UsePostgreSqlStorage,UseInMemoryStorage, etc. inside the module builder). - The core module was not registered.
- A broker dispatch or ingress adapter is present without its matching root
Add*Transport(...)registration.
Fix: register core module, storage, and dispatch before enabling processor background services. For PostgreSQL with EnsureSchemaCreationOnStartup, schema initialization runs before processor background services start. See Hosted services and Reliable Messaging.
PostgreSQL Integration Tests Reported as Skipped
Behavior. LiteBus.Storage.PostgreSql.IntegrationTests uses Testcontainers and needs Docker. Without Docker the tests are skipped with a message saying so.
Fix: start Docker Desktop or the Docker daemon, then rerun dotnet test LiteBus.slnx. To run unit tests only: dotnet test LiteBus.slnx --filter "FullyQualifiedName!~PostgreSql".
Next
Read Handler Resolution Internals to understand how the registry links handlers and why these exceptions fire when they do.