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
- If constructing manually, pass new EventHubDataAdapter(services.GetRequiredService<Serializer>()) or your custom IEventHubDataAdapter implementation.
- If using standard DI, rely on the built-in Create factory which auto-creates EventHubDataAdapter when none is registered.
- 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
- Rely on the built-in Create factory which auto-creates EventHubDataAdapter when no IEventHubDataAdapter is registered.
- When registering a custom IEventHubDataAdapter in DI, verify the factory lambda never returns null.
- In tests, construct EventHubDataAdapter with a real or mock Orleans.Serializer.
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.