dotnet/orleans · error · ArgumentNullException
Message contains no events
Error message
Message contains no events
What it means
Thrown by the SQSBatchContainer private constructor when the events list is null. A batch container must carry at least the events payload for the stream; a null list would break GetEvents<T>() and downstream serialization, so the constructor fails fast.
Source
Thrown at src/AWS/Orleans.Streaming.SQS/Streams/SQSBatchContainer.cs:57
public StreamSequenceToken SequenceToken
{
get { return sequenceToken; }
}
[JsonConstructor]
private SQSBatchContainer(
StreamId streamId,
List<object> events,
Dictionary<string, object>? requestContext,
EventSequenceTokenV2 sequenceToken)
: this(streamId, events, requestContext)
{
this.sequenceToken = sequenceToken;
}
private SQSBatchContainer(StreamId streamId, List<object> events, Dictionary<string, object>? requestContext)
{
if (events == null) throw new ArgumentNullException(nameof(events), "Message contains no events");
StreamId = streamId;
this.events = events;
this.requestContext = requestContext;
}
public IEnumerable<Tuple<T, StreamSequenceToken>> GetEvents<T>()
{
return events.OfType<T>().Select((e, i) => Tuple.Create<T, StreamSequenceToken>(e, sequenceToken.CreateSequenceTokenForEvent(i)));
}
internal static SendMessageRequest ToSQSMessage<T>(
Serializer<SQSBatchContainer> serializer,
StreamId streamId,
IEnumerable<T> events,
Dictionary<string, object>? requestContext)
{
var sqsBatchMessage = new SQSBatchContainer(streamId, events.Cast<object>().ToList(), requestContext);View on GitHub (pinned to fca799fa70)
Solutions
- Pass a non-null list; use an empty list (or short-circuit) when there are genuinely no events.
- Filter null/empty event collections before calling ToSQSMessage.
- Initialize events = new List<object>() in builders to avoid accidental nulls.
- Add a precondition check at the producer boundary.
Example fix
// before var msg = SQSBatchContainer.ToSQSMessage(serializer, streamId, null, ctx); // throws // after var events = producedEvents ?? new List<object>(); if (events.Count == 0) return; // nothing to send var msg = SQSBatchContainer.ToSQSMessage(serializer, streamId, events, ctx);
Defensive patterns
Strategy: validation
Validate before calling
var toSend = events?.ToList() ?? new List<object>();
if (toSend.Count == 0) { logger.LogDebug("No events to send; skipping batch."); return; }
var msg = SQSBatchContainer.ToSQSMessage(serializer, streamId, toSend, ctx); Type guard
static bool HasEvents<T>(IEnumerable<T>? e) => e is not null && e.Any();
Try / catch
try { /* build batch container */ }
catch (ArgumentNullException ex) when (ex.Message.Contains("no events"))
{
logger.LogWarning("Batch container built with null events; dropping batch.");
} Prevention
- Never forward null event lists; pass an empty list or skip.
- Filter empty collections at the producer boundary.
- Initialize new List<object>() in custom batch builders.
When it happens
Trigger: Constructing an SQSBatchContainer (directly or via ToSQSMessage) with a null events argument, e.g., forwarding a null enumerable from a producer that emitted no events and was not filtered out.
Common situations: Producer paths that pass through empty/null event collections; custom batch builders that forget to initialize the list; serialization round-trips that yield null on missing payloads.
Related errors
AI-assisted analysis of dotnet/orleans@fca799fa70 (2026-08-13).
Data as JSON: /api/errors/bf0abc08575c0696.
Report an issue: GitHub.