microsoft/autogen · error · InvalidOperationException

ProtoData is null.

Error message

ProtoData is null.

What it means

Thrown by GrpcAgentRuntime.HandlePublish when an incoming CloudEvent has a null ProtoData field. The runtime requires every published CloudEvent to carry its payload as protobuf-packed Any data (evt.ProtoData), which it later deserializes with a registered serializer. A null ProtoData means the event was published without a payload, so the runtime cannot route a deserializable message to agents.

Source

Thrown at dotnet/src/Microsoft.AutoGen/Core.Grpc/GrpcAgentRuntime.cs:222

        }

        if (_pendingRequests.TryRemove(request.RequestId, out var resultSink))
        {
            var payload = request.Payload;
            var message = payload.ToObject(SerializationRegistry);
            resultSink.SetResult(message);
        }
    }

    private async ValueTask HandlePublish(CloudEvent evt, CancellationToken cancellationToken = default)
    {
        if (evt is null)
        {
            throw new InvalidOperationException("CloudEvent is null.");
        }
        if (evt.ProtoData is null)
        {
            throw new InvalidOperationException("ProtoData is null.");
        }
        if (evt.Attributes is null)
        {
            throw new InvalidOperationException("Attributes is null.");
        }

        var topic = new TopicId(evt.Type, evt.Source);
        Contracts.AgentId? sender = null;
        if (evt.Attributes.TryGetValue(Constants.AGENT_SENDER_TYPE_ATTR, out var typeValue) && evt.Attributes.TryGetValue(Constants.AGENT_SENDER_KEY_ATTR, out var keyValue))
        {
            sender = new Contracts.AgentId
            {
                Type = typeValue.CeString,
                Key = keyValue.CeString
            };
        }

        var messageId = evt.Id;

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Ensure the message you publish is serialized and assigned to the CloudEvent's ProtoData (Any.Pack(protoMessage)) before sending
  2. If publishing from agent code, use the runtime's PublishMessageAsync API instead of hand-building CloudEvent instances, so the serializer registry packs the payload for you
  3. Verify the client library version matches the runtime version so it populates data_protobuf rather than a legacy payload field

Example fix

// before
var evt = new CloudEvent { Type = topic.Type, Source = topic.Source }; // no payload
await runtime.PublishMessageAsync(evt);

// after
var evt = new CloudEvent
{
    Type = topic.Type,
    Source = topic.Source,
    ProtoData = Any.Pack(myProtoMessage)
};
Defensive patterns

Strategy: validation

Validate before calling

bool CanHandle(CloudEvent evt) => evt is not null && evt.ProtoData is not null;

Type guard

static bool HasProtoPayload(CloudEvent evt) => evt?.ProtoData is not null;

Try / catch

try { await runtime.OnMessageAsync(msg); } catch (InvalidOperationException ex) when (ex.Message.Contains("ProtoData")) { _logger.LogWarning(ex, "Dropping CloudEvent without payload: {Type}/{Source}", evt.Type, evt.Source); }

Prevention

When it happens

Trigger: Calling the gRPC publish path (PublishMessageAsync on the grpc runtime, or a client sending a CloudEvent with only attributes set) with a null or unset data_protobuf field; a custom sender building a CloudEvent manually via new CloudEvent { Type = ..., Source = ... } and omitting ProtoData.

Common situations: Custom gateways or test harnesses that construct CloudEvent messages by hand; interop with non-.NET clients that publish CloudEvents without protobuf payloads; upgrades where the payload packing moved from a different field to ProtoData.

Related errors


AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15). Data as JSON: /api/errors/8b94fbb6a749b2e9. Report an issue: GitHub.