{"record":{"id":"9d76783cee304b9a","repo":"apache/beam","slug":"element-of-class-does-not-subclass-hasdisplaydata","errorCode":null,"errorMessage":"Element of class {}.{} does not subclass HasDisplayData","messagePattern":"Element of class (.+?)\\.(.+?) does not subclass HasDisplayData","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/transforms/display.py","lineNumber":243,"sourceCode":"    }\n    return cls(pipeline_options._get_display_data_namespace(), items)\n\n  @classmethod\n  def create_from(cls, has_display_data, extra_items=None):\n    \"\"\" Creates :class:`~apache_beam.transforms.display.DisplayData` from a\n    :class:`HasDisplayData` instance.\n\n    Returns:\n      ~apache_beam.transforms.display.DisplayData:\n        A :class:`~apache_beam.transforms.display.DisplayData` instance with\n        populated items.\n\n    Raises:\n      ValueError: If the **has_display_data** argument is\n        not an instance of :class:`HasDisplayData`.\n    \"\"\"\n    if not isinstance(has_display_data, HasDisplayData):\n      raise ValueError(\n          'Element of class {}.{} does not subclass HasDisplayData'.format(\n              has_display_data.__module__, has_display_data.__class__.__name__))\n    if extra_items is None:\n      extra_items = {}\n    return cls(\n        has_display_data._get_display_data_namespace(),\n        dict(**has_display_data.display_data(), **extra_items))\n\n\nclass DisplayDataItem(object):\n  \"\"\" A DisplayDataItem represents a unit of static display data.\n\n  Each item is identified by a key and the namespace of the component the\n  display item belongs to.\n  \"\"\"\n  typeDict = {\n      str: 'STRING',\n      int: 'INTEGER',","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/transforms/display.py#L225-L261","documentation":"DisplayData.create_from requires an object that subclasses HasDisplayData (transforms, DoFns, etc.). It raises ValueError when the passed object does not implement that interface, including the object's module and class in the message.","triggerScenarios":"Calling DisplayData.create_from(obj) where obj is a plain function, dict, PipelineOptions instance, or any non-HasDisplayData object.","commonSituations":"Passing a lambda/plain function instead of a DoFn; passing PipelineOptions here instead of create_from_options; passing a custom transform that forgot to inherit from PTransform/HasDisplayData.","solutions":["Pass an object that subclasses HasDisplayData (e.g. a PTransform or DoFn instance).","For pipeline options, use DisplayData.create_from_options() instead.","Make your custom class inherit HasDisplayData if it defines display_data()."],"exampleFix":"// before\ndd = DisplayData.create_from(my_plain_fn)\n// after\nclass MyDoFn(beam.DoFn):\n    def display_data(self):\n        return {'n': self.n}\ndd = DisplayData.create_from(MyDoFn(n=3))","handlingStrategy":"type-guard","validationCode":"from apache_beam.transforms.display import HasDisplayData\nassert isinstance(obj, HasDisplayData), 'create_from needs a HasDisplayData instance'","typeGuard":"def has_display_data(o) -> bool:\n    from apache_beam.transforms.display import HasDisplayData\n    return isinstance(o, HasDisplayData)","tryCatchPattern":"try:\n    dd = DisplayData.create_from(obj)\nexcept ValueError as e:\n    if 'does not subclass HasDisplayData' in str(e):\n        dd = DisplayData.create_from_options(obj)  # if it is PipelineOptions\n    else:\n        raise","preventionTips":["Make custom transforms subclass PTransform/DoFn (both are HasDisplayData)","Route PipelineOptions to create_from_options","Guard utility helpers with isinstance checks"],"tags":["apache-beam","python","display-data"],"backgroundTag":"invalid-argument-value","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"}