microsoft/autogen · error · ArgumentException

Concrete type must be a proto IMessage

Error message

Concrete type must be a proto IMessage

What it means

Thrown by ProtobufMessageSerializer.Deserialize when the serializer instance was constructed with a concrete type that does not implement Google.Protobuf.IMessage. The serializer only knows how to unpack protobuf messages, so any CLR type is rejected before deserialization is attempted.

Source

Thrown at dotnet/src/Microsoft.AutoGen/Core.Grpc/ProtobufMessageSerializer.cs:32

    private System.Type _concreteType;

    public ProtobufMessageSerializer(System.Type concreteType)
    {
        _concreteType = concreteType;
    }

    public object Deserialize(Any message)
    {
        // Check if the concrete type is a proto IMessage
        if (typeof(IMessage).IsAssignableFrom(_concreteType))
        {
            var nameOfMethod = nameof(Any.Unpack);
            var result = message.GetType().GetMethods().Where(m => m.Name == nameOfMethod && m.IsGenericMethod).First().MakeGenericMethod(_concreteType).Invoke(message, null);
            return result as IMessage ?? throw new ArgumentException("Failed to deserialize", nameof(message));
        }

        // Raise an exception if the concrete type is not a proto IMessage
        throw new ArgumentException("Concrete type must be a proto IMessage", nameof(_concreteType));
    }

    public Any Serialize(object message)
    {
        // Check if message is a proto IMessage
        if (message is IMessage protoMessage)
        {
            return Any.Pack(protoMessage);
        }

        // Raise an exception if the message is not a proto IMessage
        throw new ArgumentException("Message must be a proto IMessage", nameof(message));
    }
}

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Only use ProtobufMessageSerializer with protobuf-generated types (classes derived from IMessage via the C# codegen)
  2. For POCO/JSON messages, register the appropriate JSON-based serializer instead
  3. Ensure you pass typeof(TheGeneratedMessage), not a wrapping class or interface

Example fix

// before
new ProtobufMessageSerializer(typeof(MyDto)); // plain class

// after
new ProtobufMessageSerializer(typeof(MyProtoMessage)); // protobuf-generated
Defensive patterns

Strategy: type-guard

Validate before calling

if (!typeof(IMessage).IsAssignableFrom(concreteType)) throw new ArgumentException($"{concreteType} is not a protobuf message; use a JSON serializer");

Type guard

static bool IsProtobufMessage(Type t) => typeof(Google.Protobuf.IMessage).IsAssignableFrom(t);

Try / catch

try { return serializer.Deserialize(any); } catch (ArgumentException ex) when (ex.Message.Contains("must be a proto IMessage")) { /* fall back to JSON serializer path */ }

Prevention

When it happens

Trigger: Constructing new ProtobufMessageSerializer(typeof(SomePoco)) where SomePoco is a plain C# class rather than a protobuf-generated message; registering a non-proto type with this serializer in the serialization registry.

Common situations: Mixing protobuf and non-protobuf message contracts in one registry; passing a wrapper/DTO type instead of the generated message class; copying registration code from a proto example to a POCO type.

Related errors


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