MassTransit/MassTransit · error · ConsumerMessageException

Consumer type is not a consumer of job type

Error message

Consumer type {TypeCache<TConsumer>.ShortName} is not a consumer of job type {TypeCache<TJob>.ShortName}

What it means

JobConsumerMessageFilter.Send checks that the consumer instance implements IJobConsumer<TJob>; if it does not, it throws ConsumerMessageException stating the consumer type is not a job consumer of the given job type. MassTransit built the pipeline expecting a matching job consumer contract, so a mismatch is a configuration/registration error.

Solutions

  1. Make the consumer class implement IJobConsumer<TJob> for the job type on the endpoint
  2. Register with AddJobConsumer<TConsumer>() instead of generic AddConsumer so types are matched correctly
  3. Verify the TJob type parameter matches the job contract the endpoint is configured for

Example fix

// before
public class MyJobConsumer : IConsumer<RunJob> { ... }
// after
public class MyJobConsumer : IJobConsumer<RunJob> { ... }
Defensive patterns

Strategy: validation

Validate before calling

if (consumer is not IJobConsumer<TJob>)
    throw new InvalidOperationException($"{typeof(TConsumer).Name} must implement IJobConsumer<{typeof(TJob).Name}>");

Type guard

bool IsJobConsumer<TJb>(object c) => c is IJobConsumer<TJb>;

Try / catch

try
{
    await pipeline.Send(context);
}
catch (ConsumerMessageException ex)
{
    // registration error: consumer lacks IJobConsumer<TJob>
    logger.LogError(ex, "Job consumer registration mismatch");
}

Prevention

When it happens

Trigger: Registering a consumer type on a job endpoint where the class does not implement IJobConsumer<TJob>, or generic type parameters got mismatched (TConsumer vs TJob do not line up with the class's interfaces).

Common situations: AddJobConsumer pointing at a class that only implements IConsumer<T>; renaming TJob without updating the consumer class; copy-pasting a job consumer and forgetting the interface.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at src/MassTransit/Middleware/JobConsumerMessageFilter.cs:38

        {
            _retryPolicy = retryPolicy;
        }

        public void Probe(ProbeContext context)
        {
            var scope = context.CreateScope("consume");
            scope.Add("method", $"Consume(ConsumeContext<{TypeCache<TJob>.ShortName}> context)");
        }

        public Task Send(ConsumerConsumeContext<TConsumer, TJob> context,
            IPipe<ConsumerConsumeContext<TConsumer, TJob>> next)
        {
            if (context.Consumer is IJobConsumer<TJob> messageConsumer)
                return RunJob(context, messageConsumer);

            var message = $"Consumer type {TypeCache<TConsumer>.ShortName} is not a consumer of job type {TypeCache<TJob>.ShortName}";

            throw new ConsumerMessageException(message);
        }

        async Task RunJob(PipeContext context, IJobConsumer<TJob> jobConsumer)
        {
            var jobContext = context.GetPayload<JobContext<TJob>>();
            var notifyJobContext = context.GetPayload<INotifyJobContext>();

            RetryPolicyContext<JobContext<TJob>> policyContext = _retryPolicy.CreatePolicyContext(jobContext);

            try
            {
                await notifyJobContext.NotifyStarted().ConfigureAwait(false);

                await jobConsumer.Run(jobContext).ConfigureAwait(false);

                await notifyJobContext.NotifyCompleted().ConfigureAwait(false);
            }
            catch (OperationCanceledException exception) when (jobContext.CancellationToken == exception.CancellationToken)

View on GitHub (pinned to 62ab339afa)