dotnet/orleans · error · ArgumentNullException
cacheOptions
Error message
cacheOptions
What it means
EventHubAdapterFactory rejects a null EventHubStreamCachePressureOptions in its constructor because cache-pressure monitoring needs concrete thresholds to apply back-pressure and avoid unbounded cache growth. This options object carries the slow-consuming flow-control threshold, pressure window size, and averaging monitor threshold. Without it the adapter cannot determine when to stop reading from Event Hub partitions.
Source
Thrown at src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubAdapterFactory.cs:123
internal HashRingBasedPartitionedStreamQueueMapper EventHubQueueMapper => streamQueueMapper;
public EventHubAdapterFactory(
string name,
EventHubOptions ehOptions,
EventHubReceiverOptions receiverOptions,
EventHubStreamCachePressureOptions cacheOptions,
StreamCacheEvictionOptions cacheEvictionOptions,
StreamStatisticOptions statisticOptions,
IEventHubDataAdapter dataAdapter,
IServiceProvider serviceProvider,
ILoggerFactory loggerFactory,
IEnvironmentStatisticsProvider environmentStatisticsProvider)
{
this.Name = name;
this.cacheEvictionOptions = cacheEvictionOptions ?? throw new ArgumentNullException(nameof(cacheEvictionOptions));
this.statisticOptions = statisticOptions ?? throw new ArgumentNullException(nameof(statisticOptions));
this.ehOptions = ehOptions ?? throw new ArgumentNullException(nameof(ehOptions));
this.cacheOptions = cacheOptions?? throw new ArgumentNullException(nameof(cacheOptions));
this.dataAdapter = dataAdapter ?? throw new ArgumentNullException(nameof(dataAdapter));
this.receiverOptions = receiverOptions?? throw new ArgumentNullException(nameof(receiverOptions));
this.serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
this.environmentStatisticsProvider = environmentStatisticsProvider;
this.orleansInstruments = serviceProvider.GetRequiredService<OrleansInstruments>();
}
public virtual void Init()
{
this.receivers = new ConcurrentDictionary<QueueId, EventHubAdapterReceiver>();
InitEventHubClient();
if (this.CacheFactory == null)
{
this.CacheFactory = CreateCacheFactory(this.cacheOptions).CreateCache;
}View on GitHub (pinned to fca799fa70)
Solutions
- If constructing the factory manually, pass a new EventHubStreamCachePressureOptions() (defaults are valid) instead of null.
- If using the standard DI path, ensure AddEventHubStreams is called on the silo/client builder so that named EventHubStreamCachePressureOptions are registered.
- If subclassing EventHubAdapterFactory, do not bypass the base constructor's null-check — pass all required options through.
Example fix
// before
var factory = new EventHubAdapterFactory(
name, ehOptions, receiverOptions, null /* cacheOptions */, ...);
// after
var factory = new EventHubAdapterFactory(
name, ehOptions, receiverOptions, new EventHubStreamCachePressureOptions(), ...); Defensive patterns
Strategy: validation
Validate before calling
// Before constructing EventHubAdapterFactory manually:
if (cacheOptions is null)
throw new InvalidOperationException(
"EventHubStreamCachePressureOptions must be configured. " +
"Call .Configure<EventHubStreamCachePressureOptions>(...) or use AddEventHubStreams."); Prevention
- Prefer EventHubAdapterFactory.Create(services, name) over manual construction — it resolves all options from DI with non-null defaults.
- When subclassing EventHubAdapterFactory, always pass all constructor arguments through to the base constructor.
- Register Event Hub streams via the AddEventHubStreams extension method to ensure all options objects are in DI.
When it happens
Trigger: Constructing EventHubAdapterFactory directly with cacheOptions set to null, or a custom IQueueAdapterFactory/DI registration that supplies null for the EventHubStreamCachePressureOptions parameter. In the default EventHubAdapterFactory.Create path this is resolved via services.GetOptionByName<EventHubStreamCachePressureOptions>(name) which returns a non-null default, so this fires only on manual construction or a broken custom factory.
Common situations: Writing unit tests or a custom EventHubAdapterFactory subclass and passing null for cacheOptions; a DI container misconfiguration where a keyed/named options object is overridden with null; upgrading Orleans versions where the constructor signature changed and an outdated manual call site passes the wrong argument.
Related errors
AI-assisted analysis of dotnet/orleans@fca799fa70 (2026-08-13).
Data as JSON: /api/errors/f524511dd0b9d346.
Report an issue: GitHub.