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
- Make the consumer class implement IJobConsumer<TJob> for the job type on the endpoint
- Register with AddJobConsumer<TConsumer>() instead of generic AddConsumer so types are matched correctly
- 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
- Implement IJobConsumer<TJob> on all job endpoint consumers
- Use AddJobConsumer<T>() for registration
- Keep TJob type parameters aligned with the job contract
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
- The job service must be configured when adding job…
- The consumer specification did not match the message…
- The consumer type did not match the connector type
- jobs cannot be connected to consumer instances.
- The consumer definition was not a FutureConsumerDefinition
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)