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

  1. Pass a non-null list; use an empty list (or short-circuit) when there are genuinely no events.
  2. Filter null/empty event collections before calling ToSQSMessage.
  3. Initialize events = new List<object>() in builders to avoid accidental nulls.
  4. 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

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.