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
- Only use ProtobufMessageSerializer with protobuf-generated types (classes derived from IMessage via the C# codegen)
- For POCO/JSON messages, register the appropriate JSON-based serializer instead
- 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
- Guard serializer construction with an IMessage type check
- Keep protobuf and POCO message registrations on separate serializers
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
- Message must be a proto IMessage
- Failed to deserialize
- Failed to unpack payload into {self.cls}
- Failed to clone options
- UserInputRequestedEvent should not be sent to the completion
AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15).
Data as JSON: /api/errors/13bac3e1f193cef5.
Report an issue: GitHub.