apache/beam · error · TypeError

transform must be a subclass of BaseOperation. Got

Error message

transform must be a subclass of BaseOperation. Got: %s instead.

What it means

_validate_transform checks that every transform added to MLTransform (via with_transform or the transforms list) is an MLTransformProvider (BaseOperation subclass). Anything else — a raw model handler, callable, or wrong class — triggers this TypeError naming the actual type.

Solutions

  1. Wrap the model handler in the appropriate transform class, e.g. with_transform(SentencePieceEmbedding(model_handler=handler, columns=['text'])).
  2. Ensure you pass an instance, not the class itself.
  3. Verify the transform imports from apache_beam.ml.transforms (base operations), not another module.

Example fix

// before
mltransform.with_transform(SentencePieceTokenizerHandler(vocab_file=vocab))
// after
mltransform.with_transform(Tokenize(columns=['text'], model_handler=SentencePieceTokenizer(vocab_file=vocab)))
Defensive patterns

Strategy: type-guard

Validate before calling

from apache_beam.ml.transforms.base import MLTransformProvider
assert isinstance(embedding, MLTransformProvider), f'Got {type(embedding)}, expected a BaseOperation subclass'

Type guard

def is_valid_transform(t) -> bool:
    from apache_beam.ml.transforms.base import MLTransformProvider
    return isinstance(t, MLTransformProvider)

Try / catch

try:
    t = mltransform.with_transform(candidate)
except TypeError as e:
    if 'subclass of BaseOperation' in str(e):
        raise ValueError(f'{type(candidate)} is a handler; wrap it in a transform like Embedding/Tokenize') from e
    raise

Prevention

When it happens

Trigger: with_transform(SomeModelHandler(...)) instead of with_transform(Embedding(model_handler=...)); passing a class (not an instance); passing a plain function or an object from a different transform library.

Common situations: Confusing model handlers (e.g. SentencePieceTokenizer handler) with the transform wrappers (e.g. Tokenize) that MLTransform expects; upgrading Beam where transform class names changed.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at sdks/python/apache_beam/ml/transforms/base.py:468

      bad_pcoll = (upstream_errors | beam.Flatten())
      return pcoll, bad_pcoll  # type: ignore[return-value]
    return pcoll  # type: ignore[return-value]

  def with_transform(self, transform: MLTransformProvider):
    """
    Add a transform to the MLTransform pipeline.
    Args:
      transform: A BaseOperation instance.
    Returns:
      A MLTransform instance.
    """
    self._validate_transform(transform)
    self.transforms.append(transform)
    return self

  def _validate_transform(self, transform):
    if not isinstance(transform, MLTransformProvider):
      raise TypeError(
          'transform must be a subclass of BaseOperation. '
          'Got: %s instead.' % type(transform))

  def with_exception_handling(
      self, *, exc_class=Exception, use_subprocess=False, threshold=1):
    self._with_exception_handling = True
    self._exception_handling_args = {
        'exc_class': exc_class,
        'use_subprocess': use_subprocess,
        'threshold': threshold
    }
    return self


class MLTransformMetricsUsage(beam.PTransform):
  def __init__(self, ml_transform: MLTransform):
    self._ml_transform = ml_transform
    self._ml_transform._counter.inc()

View on GitHub (pinned to 12126d8942)