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
- Wrap the model handler in the appropriate transform class, e.g. with_transform(SentencePieceEmbedding(model_handler=handler, columns=['text'])).
- Ensure you pass an instance, not the class itself.
- 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
- Never pass model handlers directly to with_transform; use transform wrapper classes
- Pass instances, not classes
- Add an isinstance(MLTransformProvider) assert in pipeline-construction tests
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
- A sink must inherit iobase.Sink, iobase.NativeSink, or be a…
- Cannot encode payload for WriteToPubSub. Expected valid…
- Cannot interpret as seconds.
- Cannot interpret as subseconds.
- compression_type must be CompressionType object but was
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)