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.

Solutions

  1. If constructing the factory manually, pass a new EventHubStreamCachePressureOptions() (defaults are valid) instead of null.
  2. If using the standard DI path, ensure AddEventHubStreams is called on the silo/client builder so that named EventHubStreamCachePressureOptions are registered.
  3. 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

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.

Appendix: 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)