dotnet/orleans · error · ArgumentNullException

serviceProvider

Error message

serviceProvider

What it means

EventHubAdapterFactory requires a non-null IServiceProvider because it is used immediately at construction time to resolve OrleansInstruments (via GetRequiredService) and later during Init/MakeReceiver to resolve keyed checkpointer factories, LoadSheddingOptions, and other framework services. A null service provider would cause a NullReferenceException at the very next line (GetRequiredService<OrleansInstruments>), so the null check fails fast with a clearer message.

Source

Thrown at src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubAdapterFactory.cs:126

            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;
            }

            if (this.StreamFailureHandlerFactory == null)
            {

View on GitHub (pinned to fca799fa70)

Solutions

  1. Always pass the IServiceProvider obtained from the silo/client's service collection.
  2. In tests, build a minimal ServiceCollection with the required services (OrleansInstruments, ILoggerFactory, IEnvironmentStatisticsProvider, etc.) and pass its BuildServiceProvider().
  3. Use EventHubAdapterFactory.Create(services, name) which correctly threads the provider through.

Example fix

// before
var factory = new EventHubAdapterFactory(
    name, ehOptions, receiverOptions, cacheOptions, evictionOpts, statOpts, dataAdapter, null /* serviceProvider */, loggerFactory, envStats);

// after
var services = new ServiceCollection()
    .AddSingleton<ILoggerFactory>(loggerFactory)
    .AddSingleton<OrleansInstruments>()
    .BuildServiceProvider();
var factory = new EventHubAdapterFactory(
    name, ehOptions, receiverOptions, cacheOptions, evictionOpts, statOpts, dataAdapter, services, loggerFactory, envStats);
Defensive patterns

Strategy: validation

Validate before calling

// Ensure IServiceProvider is available:
if (serviceProvider is null)
    throw new InvalidOperationException(
        "An IServiceProvider is required. Build one from a ServiceCollection " +
        "with the necessary Orleans services registered.");

Prevention

When it happens

Trigger: Constructing EventHubAdapterFactory directly with serviceProvider set to null. The default Create factory always passes the IServiceProvider from the factory's own services parameter, so this fires only when a caller manually constructs the adapter or a custom factory method passes null.

Common situations: Manual construction outside of DI (e.g., in a unit test or a non-standard hosting path) where no IServiceProvider is available; a custom factory or ActivatorUtilities.CreateInstance call where the services argument is accidentally omitted or null.

Related errors


AI-assisted analysis of dotnet/orleans@fca799fa70 (2026-08-13). Data as JSON: /api/errors/4e73404ad58e8738. Report an issue: GitHub.