MassTransit/MassTransit · error · MassTransitException

DisposeAsync

Error message

DisposeAsync

What it means

This DisposeAsync extension guarantees the original exception is not lost: if the async-dispose callback itself faults, it runs the dispose callback, rethrows the captured dispatch exception via dispatchInfo.Throw(), and otherwise throws MassTransitException('DisposeAsync', exception) to wrap the failure. Seeing this means an exception occurred during an async disposable's DisposeAsync while a primary exception was already in flight.

Solutions

  1. Inspect the inner 'exception' property for the root cause — this wrapper masks a primary fault
  2. Log both the disposal failure and the wrapped original exception
  3. Fix the underlying operation failure that put the disposable into a faulted state
  4. Ensure DisposeAsync is awaited and resources are not double-disposed

Example fix

// before
await client.DisposeAsync(); // hides wrapped fault
// after
try { await client.DisposeAsync(); }
catch (MassTransitException ex) when (ex.Message == "DisposeAsync")
{
    _logger.LogError(ex.InnerException, "Faulted during dispose");
    throw ex.InnerException ?? ex;
}
Defensive patterns

Strategy: try-catch

Try / catch

try { await x.DisposeAsync(); } catch (MassTransitException ex) { log(ex.InnerException ?? ex); }

Prevention

When it happens

Trigger: Calling DisposeAsync() on an async-disposable (e.g. a bus, client, or receive endpoint handle) when the underlying operation already faulted and the dispose callback also threw, or the captured exception could not be rethrown.

Common situations: Bus shutdown while a send/fault was pending; 'using await' scopes whose body threw and whose disposal also failed; cancellation during dispose; clients disposed in finally blocks after failures.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.


AI-assisted analysis of MassTransit/MassTransit@62ab339afa (2026-09-13). Data as JSON: /api/errors/8ce6267b4ba7a24a. Report an issue: GitHub.

Appendix: source

Thrown at src/MassTransit/Util/DisposeAsyncExtensions.cs:28

        /// <summary>
        /// Invoke the dispose callback, and then rethrow the exception
        /// </summary>
        /// <param name="exception"></param>
        /// <param name="disposeCallback"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        /// <exception cref="MassTransitException"></exception>
        public static ValueTask<T> DisposeAsync<T>(this Exception exception, Func<Task> disposeCallback)
        {
            var dispatchInfo = ExceptionDispatchInfo.Capture(exception.GetBaseException());

            async ValueTask<T> Faulted()
            {
                await disposeCallback().ConfigureAwait(false);

                dispatchInfo.Throw();

                throw new MassTransitException("DisposeAsync", exception);
            }

            return Faulted();
        }

        /// <summary>
        /// Invoke the dispose callback, and then rethrow the exception
        /// </summary>
        /// <param name="exception"></param>
        /// <param name="disposeCallback"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        /// <exception cref="MassTransitException"></exception>
        public static ValueTask<T> DisposeAsync<T>(this Exception exception, Func<ValueTask> disposeCallback)
        {
            var dispatchInfo = ExceptionDispatchInfo.Capture(exception.GetBaseException());

            async ValueTask<T> Faulted()

View on GitHub (pinned to 62ab339afa)