{"record":{"id":"a9d3e0bc74576c4f","repo":"apache/beam","slug":"coder-registration-requires-a-coder-class-object-received-r","errorCode":null,"errorMessage":"Coder registration requires a coder class object. Received %r instead.","messagePattern":"Coder registration requires a coder class object\\. Received %r instead\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/coders/typecoders.py","lineNumber":138,"sourceCode":"\n  def register_coder(\n      self, typehint_type: Any,\n      typehint_coder_class: type[coders.Coder]) -> None:\n    \"\"\"\n    Register a user type with a coder.\n\n    Typical usage::\n\n      class MyCustomType:\n        pass\n\n      coders.registry.register_coder(MyCustomType, MyCustomCoder)\n\n    To register a supported user type (data class or named tuple) with Beam Row,\n    use :meth:`register_row` instead, as it registers both coder and schema.\n    \"\"\"\n    if not isinstance(typehint_coder_class, type):\n      raise TypeError(\n          'Coder registration requires a coder class object. '\n          'Received %r instead.' % typehint_coder_class)\n    if typehint_type not in self.custom_types:\n      self.custom_types.append(typehint_type)\n    self._register_coder_internal(\n        self._normalize_typehint_type(typehint_type), typehint_coder_class)\n\n  def register_row(self, typehint_type: type[Any]) -> type[Any]:\n    \"\"\"\n    Register a user type with a Beam Row.\n\n    This registers the type with a RowCoder and register its schema.\n\n    Register a dataclass::\n\n      @coders.registry.register_row\n      @dataclass\n      class MyDataClass:","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/coders/typecoders.py#L120-L156","documentation":"CoderRegistry.register_coder maps a type hint to a coder class. It requires the coder argument to be an actual class (type), not an instance or other object; anything else raises TypeError. Instances are rejected because coders are instantiated per-pipeline by the registry.","triggerScenarios":"Calling registry.register_coder(MyType, MyCoder()) with an instance instead of the class; passing a functools.partial, lambda, or a mocked object; accidentally shadowing the coder class with a variable holding an instance.","commonSituations":"Users wiring custom coders in __init__ or pipeline setup; copying example code and instantiating the coder; test fakes substituting a mock for the class.","solutions":["Pass the coder class itself, not an instance: register_coder(MyType, MyCoder).","Ensure the coder subclasses Coder and is defined at module level.","For dataclasses/named tuples use register_row instead of register_coder.","Check for name shadowing where MyCoder was reassigned to an instance earlier."],"exampleFix":"// before\nregistry.register_coder(MyCustomType, MyCustomCoder())\n// after\nregistry.register_coder(MyCustomType, MyCustomCoder)","handlingStrategy":"type-guard","validationCode":"if not isinstance(coder_cls, type):\n    raise TypeError('register_coder expects a class, got instance/other')","typeGuard":"def is_coder_class(obj) -> bool:\n    import inspect\n    from apache_beam.coders import Coder\n    return isinstance(obj, type) and inspect.isclass(obj) and issubclass(obj, Coder)","tryCatchPattern":"try:\n    typecoders.registry.register_coder(my_type, coder_cls)\nexcept TypeError as e:\n    if 'coder class object' in str(e):\n        coder_cls = type(coder_cls)  # unwrap accidental instance\n        typecoders.registry.register_coder(my_type, coder_cls)\n    else:\n        raise","preventionTips":["Never instantiate coders when registering; pass the class.","Keep coder classes module-level so pickling and lookup work.","Use register_row for dataclasses/NamedTuples.","Add an assert issubclass(MyCoder, Coder) near registration."],"tags":["python","coders","type-error","registration"],"backgroundTag":"type-mismatch","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}