dotnet/orleans · error · NotSupportedException
Specified method is not supported.
Error message
Specified method is not supported.
What it means
StreamActivityNotificationBatch is an internal IBatchContainer implementation used by EventHubAdapterReceiver solely to signal stream activity (a new message arrived) — it carries only a StreamPosition and does not hold actual event payloads. Its GetEvents<T>() and ImportRequestContext() methods throw NotSupportedException because the batch has no deserializable events and no request context to import. Calling these methods indicates the consumer is treating a notification-only batch as a full data batch.
Source
Thrown at src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubAdapterReceiver.cs:405
{
(this.receiver as EventHubPartitionGeneratorReceiver)?.StopProducingOnStream(streamId);
}
[GenerateSerializer]
internal class StreamActivityNotificationBatch : IBatchContainer
{
[Id(0)]
public StreamPosition Position { get; }
public StreamId StreamId => this.Position.StreamId;
public StreamSequenceToken SequenceToken => this.Position.SequenceToken;
public StreamActivityNotificationBatch(StreamPosition position)
{
this.Position = position;
}
public IEnumerable<Tuple<T, StreamSequenceToken>> GetEvents<T>() { throw new NotSupportedException(); }
public bool ImportRequestContext() { throw new NotSupportedException(); }
}
private class Cursor : IQueueCacheCursor
{
private readonly IEventHubQueueCache cache;
private readonly object cursor;
private IBatchContainer? current;
public Cursor(IEventHubQueueCache cache, StreamId streamId, StreamSequenceToken? token)
{
this.cache = cache;
this.cursor = cache.GetCursor(streamId, token);
}
public void Dispose()
{
}View on GitHub (pinned to fca799fa70)
Solutions
- Do not call GetEvents<T>() or ImportRequestContext() directly on batches from GetQueueMessagesAsync — these are activity notifications, not data containers.
- Use the IQueueCacheCursor (obtained via GetCacheCursor) to read actual event data, which resolves the real EventHubBatchContainer from the cache.
- If building custom streaming infrastructure, check the batch type before calling GetEvents — if it is StreamActivityNotificationBatch, treat it as a signal only.
Example fix
// before
var batches = await receiver.GetQueueMessagesAsync(maxCount, ct);
foreach (var batch in batches)
{
var events = batch.GetEvents<MyEvent>(); // throws NotSupportedException
}
// after
var batches = await receiver.GetQueueMessagesAsync(maxCount, ct);
// batches are activity notifications; actual events are read via cache cursor
var cursor = receiver.GetCacheCursor(streamId, token);
while (cursor.MoveNext())
{
var batch = cursor.GetCurrent(out var ex);
// batch is now the real EventHubBatchContainer with actual events
} Defensive patterns
Strategy: type-guard
Type guard
// Check if the batch is a notification-only container before calling GetEvents:
static bool IsDataBatch(IBatchContainer batch)
=> batch.GetType().Name is not "StreamActivityNotificationBatch";
// Or check capability before calling:
static IEnumerable<Tuple<T, StreamSequenceToken>>? SafeGetEvents<T>(IBatchContainer batch)
{
if (batch.GetType().Name == "StreamActivityNotificationBatch")
return null; // notification-only, no events
try { return batch.GetEvents<T>(); }
catch (NotSupportedException) { return null; }
} Prevention
- Never call GetEvents<T>() or ImportRequestContext() on IBatchContainer objects from GetQueueMessagesAsync — use the cache cursor instead.
- Use IQueueCacheCursor (GetCacheCursor/MoveNext/GetCurrent) to read actual event data from the cache.
- If building custom stream infrastructure, type-check batches before invoking data-access methods.
When it happens
Trigger: Code that receives an IBatchContainer from the EventHub stream's EventHubAdapterReceiver.GetQueueMessagesAsync and calls GetEvents<T>() or ImportRequestContext() on it. This happens when a consumer bypasses the IQueueCacheCursor path (which resolves the real batch container from the cache) and instead directly processes the StreamActivityNotificationBatch objects returned by GetQueueMessagesAsync.
Common situations: A custom stream extension or observer infrastructure that enumerates IBatchContainer.GetEvents<T>() on batches obtained from the receiver before they go through cache cursor resolution; incorrect assumption that all IBatchContainer instances support GetEvents; an Orleans internal code path regression after an upgrade.
Related errors
- This adapter only supports read
- Cannot get events from a half-baked {nameof(AdoNetBatchConta
- Specified method is not supported.
- This stream is read-only.
- cacheOptions
AI-assisted analysis of dotnet/orleans@fca799fa70 (2026-08-13).
Data as JSON: /api/errors/3f04aa622d57ca2e.
Report an issue: GitHub.