microsoft/autogen · error · ValueError

Failed to unpack payload into {self.cls}

Error message

Failed to unpack payload into {self.cls}

What it means

ProtobufMessageSerializer.deserialize wraps payloads in google.protobuf.Any; Unpack fails (returns False) when the embedded message's concrete type does not match the registered self.cls. The code then raises ValueError, meaning the bytes were valid Any-encoded data but not the protobuf message type this serializer expects.

Source

Thrown at python/packages/autogen-core/src/autogen_core/_serialization.py:177

        self.cls = cls

    @property
    def data_content_type(self) -> str:
        return PROTOBUF_DATA_CONTENT_TYPE

    @property
    def type_name(self) -> str:
        return _type_name(self.cls)

    def deserialize(self, payload: bytes) -> ProtobufT:
        # Parse payload into a proto any
        any_proto = any_pb2.Any()
        any_proto.ParseFromString(payload)

        destination_message = self.cls()

        if not any_proto.Unpack(destination_message):  # type: ignore
            raise ValueError(f"Failed to unpack payload into {self.cls}")

        return destination_message

    def serialize(self, message: ProtobufT) -> bytes:
        any_proto = any_pb2.Any()
        any_proto.Pack(message)  # type: ignore
        return any_proto.SerializeToString()


@dataclass
class UnknownPayload:
    type_name: str
    data_content_type: str
    payload: bytes


def _type_name(cls: type[Any] | Any) -> str:
    # If cls is a protobuf, then we need to determine the descriptor

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Verify both ends register ProtobufMessageSerializer for the exact same generated protobuf class
  2. Check any_proto.Is(destination_message) before unpacking, or catch ValueError and log payload diagnostic info (type_url)
  3. Ensure the type_name used in registration is unique per message class so payloads are routed to the right serializer
  4. Regenerate Python protobuf stubs on all processes after editing .proto files

Example fix

# before
msg = serializer.deserialize(payload)  # ValueError if wrong type

# after
from google.protobuf import any_pb2
any_proto = any_pb2.Any()
any_proto.ParseFromString(payload)
if not any_proto.Is(MessageTypeA()):
    raise TypeError(f"got {any_proto.type_url}, expected {MessageTypeA.DESCRIPTOR.full_name}")
msg = serializer.deserialize(payload)
Defensive patterns

Strategy: try-catch

Validate before calling

from google.protobuf import any_pb2

def payload_matches(payload: bytes, cls) -> bool:
    a = any_pb2.Any()
    if not a.ParseFromString(payload):
        return False
    return a.Is(cls())

Type guard

def is_registered_proto(serializer, cls) -> bool:
    return serializer.cls is cls

Try / catch

try:
    msg = serializer.deserialize(payload)
except ValueError as e:
    if "Failed to unpack" in str(e):
        a = any_pb2.Any(); a.ParseFromString(payload)
        raise TypeError(f"payload was {a.type_url}, expected {serializer.cls.DESCRIPTOR.full_name}") from e
    raise

Prevention

When it happens

Trigger: A message arrives on a serializer registered for MessageTypeA but the payload contains MessageTypeB packed in Any; two agents use different .proto definitions for the same type_name; the payload is corrupted or not Any-wrapped at all (e.g. raw JSON sent to a protobuf serializer, or content-type mismatch on the wire).

Common situations: Schema drift between publisher and subscriber protobuf definitions; reusing a type_name across different message classes; cross-runtime (grpc worker) setups where one side was not rebuilt after a .proto change; serializing with serialize() but deserializing with a serializer constructed for a different generated class.

Related errors


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