{"record":{"id":"8b1d0c1520ce0bbf","repo":"apache/beam","slug":"transforms-must-be-instances-of-mltransformprovider-and","errorCode":null,"errorMessage":"Transforms must be instances of MLTransformProvider and implement get_ptransform_for_processing() method.","messagePattern":"Transforms must be instances of MLTransformProvider and implement get_ptransform_for_processing\\(\\) method\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/ml/transforms/base.py","lineNumber":633,"sourceCode":"      pipeline_options: Optional[PipelineOptions] = None,\n  ):\n    self.transforms = transforms\n    self._parent_artifact_location = artifact_location\n    self.artifact_mode = artifact_mode\n    self.pipeline_options = pipeline_options\n\n  def create_and_save_ptransform_list(self):\n    ptransform_list = self.create_ptransform_list()\n    self.save_transforms_in_artifact_location(ptransform_list)\n    return ptransform_list\n\n  def create_ptransform_list(self):\n    previous_ptransform_type = None\n    current_ptransform = None\n    ptransform_list = []\n    for transform in self.transforms:\n      if not isinstance(transform, MLTransformProvider):\n        raise RuntimeError(\n            'Transforms must be instances of MLTransformProvider and '\n            'implement get_ptransform_for_processing() method.')\n      # for each instance of PTransform, create a new artifact location\n      current_ptransform = transform.get_ptransform_for_processing(\n          artifact_location=os.path.join(\n              self._parent_artifact_location, uuid.uuid4().hex[:6]),\n          artifact_mode=self.artifact_mode)\n      append_transform = hasattr(current_ptransform, 'append_transform')\n      if (type(current_ptransform)\n          != previous_ptransform_type) or not append_transform:\n        ptransform_list.append(current_ptransform)\n        previous_ptransform_type = type(current_ptransform)\n      # If different PTransform is appended to the list and the PTransform\n      # supports append_transform, append the transform to the PTransform.\n      if append_transform:\n        ptransform_list[-1].append_transform(transform)\n    return ptransform_list\n","sourceCodeStart":615,"sourceCodeEnd":651,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/ml/transforms/base.py#L615-L651","documentation":"create_ptransform_list validates that every transform passed to MLTransform is an instance of MLTransformProvider and can produce a PTransform via get_ptransform_for_processing(). If any element in the transforms list is not such a provider (e.g. a raw PTransform or arbitrary callable), RuntimeError is raised before any processing happens.","triggerScenarios":"Passing a plain apache_beam.transforms.PTransform, a lambda, or a non-ML transform class instance into MLTransform(transforms=[...]) instead of instances of MLTransformProvider subclasses (e.g. built-in embeddings/handlers).","commonSituations":"Mixing generic Beam transforms (Map, ParDo) into the MLTransform transforms list; writing a custom transform but forgetting to subclass MLTransformProvider; passing a class where an instance is required or vice versa.","solutions":["Only pass instances whose class subclasses MLTransformProvider and implements get_ptransform_for_processing().","Wrap your custom logic: class MyTransform(MLTransformProvider): def get_ptransform_for_processing(self, **kwargs): return MyPTransform().","Move non-ML Beam transforms outside MLTransform in the pipeline (before/after the MLTransform step)."],"exampleFix":"// before\nMLTransform().with_transform(beam.Map(lambda x: x))\n// after\nclass MyTransform(MLTransformProvider):\n  def get_ptransform_for_processing(self, **kwargs):\n    return beam.Map(lambda x: x)\nMLTransform().with_transform(MyTransform())","handlingStrategy":"type-guard","validationCode":"from apache_beam.ml.transforms.base import MLTransformProvider\nbad = [t for t in transforms if not isinstance(t, MLTransformProvider)]\nassert not bad, f'Not MLTransformProvider: {bad}'","typeGuard":"def is_ml_transform(t) -> bool:\n    return isinstance(t, MLTransformProvider) and hasattr(t, 'get_ptransform_for_processing')","tryCatchPattern":"try:\n    create_ptransform_list()\nexcept RuntimeError as e:\n    if 'MLTransformProvider' in str(e):\n        transforms = [wrap(t) for t in transforms]\n    else:\n        raise","preventionTips":["Only pass MLTransformProvider instances to MLTransform.","Subclass MLTransformProvider for custom transforms and implement get_ptransform_for_processing().","Keep plain Beam PTransforms outside the MLTransform transforms list.","Unit-test custom transform classes instantiate and return a PTransform."],"tags":["python","type-mismatch","mltransform"],"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"}