{"record":{"id":"13bac3e1f193cef5","repo":"microsoft/autogen","slug":"concrete-type-must-be-a-proto-imessage","errorCode":null,"errorMessage":"Concrete type must be a proto IMessage","messagePattern":"Concrete type must be a proto IMessage","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Microsoft.AutoGen/Core.Grpc/ProtobufMessageSerializer.cs","lineNumber":32,"sourceCode":"    private System.Type _concreteType;\n\n    public ProtobufMessageSerializer(System.Type concreteType)\n    {\n        _concreteType = concreteType;\n    }\n\n    public object Deserialize(Any message)\n    {\n        // Check if the concrete type is a proto IMessage\n        if (typeof(IMessage).IsAssignableFrom(_concreteType))\n        {\n            var nameOfMethod = nameof(Any.Unpack);\n            var result = message.GetType().GetMethods().Where(m => m.Name == nameOfMethod && m.IsGenericMethod).First().MakeGenericMethod(_concreteType).Invoke(message, null);\n            return result as IMessage ?? throw new ArgumentException(\"Failed to deserialize\", nameof(message));\n        }\n\n        // Raise an exception if the concrete type is not a proto IMessage\n        throw new ArgumentException(\"Concrete type must be a proto IMessage\", nameof(_concreteType));\n    }\n\n    public Any Serialize(object message)\n    {\n        // Check if message is a proto IMessage\n        if (message is IMessage protoMessage)\n        {\n            return Any.Pack(protoMessage);\n        }\n\n        // Raise an exception if the message is not a proto IMessage\n        throw new ArgumentException(\"Message must be a proto IMessage\", nameof(message));\n    }\n}\n","sourceCodeStart":14,"sourceCodeEnd":47,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/dotnet/src/Microsoft.AutoGen/Core.Grpc/ProtobufMessageSerializer.cs#L14-L47","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nnew ProtobufMessageSerializer(typeof(MyDto)); // plain class\n\n// after\nnew ProtobufMessageSerializer(typeof(MyProtoMessage)); // protobuf-generated","handlingStrategy":"type-guard","validationCode":"if (!typeof(IMessage).IsAssignableFrom(concreteType)) throw new ArgumentException($\"{concreteType} is not a protobuf message; use a JSON serializer\");","typeGuard":"static bool IsProtobufMessage(Type t) => typeof(Google.Protobuf.IMessage).IsAssignableFrom(t);","tryCatchPattern":"try { return serializer.Deserialize(any); } catch (ArgumentException ex) when (ex.Message.Contains(\"must be a proto IMessage\")) { /* fall back to JSON serializer path */ }","preventionTips":["Guard serializer construction with an IMessage type check","Keep protobuf and POCO message registrations on separate serializers"],"tags":["protobuf","serialization","type-validation"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}