apache/beam · error · ValueError

Expected a strict subclass of google.protobuf.message.Messag

Error message

Expected a strict subclass of google.protobuf.message.Message, but got a %s

What it means

ProtoCoder only accepts classic google.protobuf Message subclasses (not proto-plus wrappers). from_type_hint validates that the typehint is a strict subclass of google.protobuf.message.Message; anything else (including Message itself or a proto-plus type) raises ValueError.

Source

Thrown at sdks/python/apache_beam/coders/coders.py:1196

        type(self) == type(other) and
        self.proto_message_type == other.proto_message_type)

  def __hash__(self):
    return hash(self.proto_message_type)

  @classmethod
  def from_type_hint(cls, typehint, unused_registry):
    # The typehint must be a strict subclass of google.protobuf.message.Message.
    # ProtoCoder cannot work with message.Message itself, as deserialization of
    # a serialized proto requires knowledge of the desired concrete proto
    # subclass which is not stored in the encoded bytes themselves. If this
    # occurs, an error is raised and the system defaults to other fallback
    # coders.
    if (issubclass(typehint, proto_utils.message_types) and
        typehint != message.Message):
      return cls(typehint)
    else:
      raise ValueError((
          'Expected a strict subclass of google.protobuf.message.Message'
          ', but got a %s' % typehint))

  def to_type_hint(self):
    return self.proto_message_type


class DeterministicProtoCoder(ProtoCoder):
  """A deterministic Coder for Google Protocol Buffers.

  It supports both Protocol Buffers syntax versions 2 and 3. However,
  the runtime version of the python protobuf library must exactly match the
  version of the protoc compiler what was used to generate the protobuf
  messages.
  """
  def _create_impl(self):
    return coder_impl.DeterministicProtoCoderImpl(self.proto_message_type)

View on GitHub (pinned to 12126d8942)

Solutions

  1. Use the concrete generated protobuf class (e.g. my_pb2.MyMessage) as the typehint
  2. If your messages use proto-plus, use ProtoPlusCoder instead of ProtoCoder
  3. Verify with proto_utils.is_message_type(typehint) before constructing

Example fix

// before
coder = ProtoCoder.from_type_hint(message.Message, registry)
// after
coder = ProtoCoder.from_type_hint(school_pb2.Student, registry)
Defensive patterns

Strategy: type-guard

Validate before calling

from google.protobuf import message
from apache_beam.utils import proto_utils
can_use = isinstance(typehint, type) and issubclass(typehint, message.Message) and typehint is not message.Message

Type guard

def is_classic_proto_class(t) -> bool:
    from google.protobuf import message
    return isinstance(t, type) and issubclass(t, message.Message) and t is not message.Message

Try / catch

try:
    coder = ProtoCoder.from_type_hint(typehint, registry)
except ValueError:
    coder = ProtoPlusCoder.from_type_hint(typehint, registry)

Prevention

When it happens

Trigger: Creating a ProtoCoder via from_type_hint with a typehint that is google.protobuf.message.Message itself, a proto-plus message class, or a non-protobuf class.

Common situations: Mixing proto-plus (new protobuf API) types with ProtoCoder; annotating a DoFn with a base Message class instead of the concrete generated class; pipeline type inference handing the wrong typehint.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/6e73fb2b91a3aafb. Report an issue: GitHub.