MassTransit/MassTransit · error · ArgumentException
The configurator must be a consumer specification
Error message
The configurator must be a consumer specification
What it means
BatchConsumerConfigured on MessageScopeConfigurationObserver expects the configurator passed by the pipe to also implement IConsumerMessageSpecification<TConsumer, Batch<TMessage>> so scope filters can be added. This defensive cast failure indicates the observer was attached to a configurator type that does not implement the expected specification interface - an internal contract violation, normally caused by a custom configurator, a mismatched observer registration, or a MassTransit/container package version mismatch.
Solutions
- Align all MassTransit package versions (MassTransit and MassTransit.Abstractions) to the same release
- Register the observer only via the standard AddMassTransit configuration path, not manually
- Check any custom IConsumerMessageConfigurator implementations implement the matching IConsumerMessageSpecification interface
- Report as a bug if it occurs with stock configurators on aligned versions
Example fix
// before
observer.BatchConsumerConfigured<TConsumer, TMessage>(customConfigurator); // customConfigurator lacks IConsumerMessageSpecification
// after
var consumerSpecification = customConfigurator as IConsumerMessageSpecification<TConsumer, Batch<TMessage>>;
if (consumerSpecification == null) throw new ArgumentException("Custom configurator must implement IConsumerMessageSpecification"); Defensive patterns
Strategy: try-catch
Validate before calling
var consumerSpecification = configurator as IConsumerMessageSpecification<TConsumer, Batch<TMessage>>;
if (consumerSpecification == null) throw new InvalidOperationException("Attach MessageScopeConfigurationObserver only to standard MassTransit consumer configurators"); Type guard
static bool IsConsumerMessageSpecification<TConsumer,TMessage>(IConsumerMessageConfigurator<TConsumer, Batch<TMessage>> c) => c is IConsumerMessageSpecification<TConsumer, Batch<TMessage>>;
Try / catch
try { observer.BatchConsumerConfigured<TConsumer, TMessage>(configurator); } catch (ArgumentException ex) when (ex.Message == "The configurator must be a consumer specification") { /* log; indicates version mismatch or custom configurator bug */ } Prevention
- Keep all MassTransit packages on the same version
- Avoid custom IConsumerMessageConfigurator implementations for Batch<TMessage>
- Attach observers via the standard AddMassTransit pipeline, not manually
When it happens
Trigger: Attaching MessageScopeConfigurationObserver (directly or via AddMassTransit scoped-consume wiring) while a custom or third-party IConsumerMessageConfigurator for Batch<TMessage> does not implement IConsumerMessageSpecification<TConsumer, Batch<TMessage>>; registering batch consumers with mismatched MassTransit.Abstractions/MassTransit versions.
Common situations: Mixed NuGet package versions (MassTransit vs MassTransit.Abstractions) during an upgrade; custom consumer configurators that violate the interface contract; manually adding the observer in an unusual configuration rather than via standard AddMassTransit.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- At least one response must have completed
- The bus registration context cannot be null (via AddConfigur
- sendEndpointProvider
- publishEndpoint
- The configurator must be a consumer specification
AI-assisted analysis of MassTransit/MassTransit@62ab339afa (2026-09-13).
Data as JSON: /api/errors/0132fa91b6211704.
Report an issue: GitHub.
Appendix: source
Thrown at src/MassTransit/DependencyInjection/Configuration/MessageScopeConfigurationObserver.cs:43
_setScopedConsumeContext = setScopedConsumeContext;
Connect(this);
}
public void MessageConfigured<TMessage>(IConsumePipeConfigurator configurator)
where TMessage : class
{
var scopeProvider = new ConsumeScopeProvider(_serviceProvider, _setScopedConsumeContext);
var scopeFilter = new ScopeMessageFilter<TMessage>(scopeProvider);
var specification = new FilterPipeSpecification<ConsumeContext<TMessage>>(scopeFilter);
configurator.AddPipeSpecification(specification);
}
public override void BatchConsumerConfigured<TConsumer, TMessage>(IConsumerMessageConfigurator<TConsumer, Batch<TMessage>> configurator)
{
if (!(configurator is IConsumerMessageSpecification<TConsumer, Batch<TMessage>> consumerSpecification))
throw new ArgumentException("The configurator must be a consumer specification");
var scopeProvider = new ConsumeScopeProvider(_serviceProvider, _setScopedConsumeContext);
var scopeFilter = new ScopeMessageFilter<Batch<TMessage>>(scopeProvider);
var specification = new FilterPipeSpecification<ConsumeContext<Batch<TMessage>>>(scopeFilter);
consumerSpecification.AddPipeSpecification(specification);
}
public override void ActivityConfigured<TActivity, TArguments>(IExecuteActivityConfigurator<TActivity, TArguments> configurator, Uri compensateAddress)
{
var scopeProvider = new ExecuteActivityScopeProvider<TActivity, TArguments>(_serviceProvider, _setScopedConsumeContext);
var scopeFilter = new ScopeExecuteFilter<TActivity, TArguments>(scopeProvider);
var specification = new FilterPipeSpecification<ExecuteContext<TArguments>>(scopeFilter);
configurator.Arguments(x => x.AddPipeSpecification(specification));
}
public override void ExecuteActivityConfigured<TActivity, TArguments>(IExecuteActivityConfigurator<TActivity, TArguments> configurator)View on GitHub (pinned to 62ab339afa)