dotnet/orleans · error · ArgumentNullException

dataAdapter

Error message

dataAdapter

What it means

EventHubAdapterFactory requires a non-null IEventHubDataAdapter because it is the core bridge between Event Hub EventData and Orleans stream types (StreamId, StreamSequenceToken, CachedMessage, IBatchContainer). Without it the adapter cannot serialize batch containers, compute partition keys, or translate incoming messages. The default implementation is EventHubDataAdapter, which users may subclass to customize mapping.

Source

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

        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

  1. If constructing manually, pass new EventHubDataAdapter(services.GetRequiredService<Serializer>()) or your custom IEventHubDataAdapter implementation.
  2. If using standard DI, rely on the built-in Create factory which auto-creates EventHubDataAdapter when none is registered.
  3. If registering a custom IEventHubDataAdapter, verify the registration factory never returns null.

Example fix

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

// after
var dataAdapter = new EventHubDataAdapter(services.GetRequiredService<Orleans.Serialization.Serializer>());
var factory = new EventHubAdapterFactory(
    name, ehOptions, receiverOptions, cacheOptions, evictionOpts, statOpts, dataAdapter, services, loggerFactory, envStats);
Defensive patterns

Strategy: validation

Validate before calling

// Before constructing manually:
IEventHubDataAdapter dataAdapter = customAdapter
    ?? new EventHubDataAdapter(services.GetRequiredService<Orleans.Serialization.Serializer>());

Type guard

static bool IsValidDataAdapter(IEventHubDataAdapter adapter)
    => adapter is not null;

Prevention

When it happens

Trigger: Constructing EventHubAdapterFactory directly with dataAdapter set to null. In the default factory Create method, the data adapter is resolved as services.GetKeyedService<IEventHubDataAdapter>(name) ?? services.GetService<IEventHubDataAdapter>() ?? ActivatorUtilities.CreateInstance<EventHubDataAdapter>(services), which guarantees a non-null value — so this only fires on manual construction or a custom factory that explicitly returns null.

Common situations: Manually building the adapter in tests or a custom factory and forgetting the dataAdapter argument; a DI container where an IEventHubDataAdapter registration is accidentally registered as null via a factory lambda returning null.

Related errors


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