apache/beam · error · RuntimeError
Unsupported transform
Error message
Unsupported transform {transform_id} of type {transform_proto.spec.urn} What it means
The TrivialRunner (a single-process runner used mainly for testing) encountered a PTransform whose URN it does not know how to execute during execute_transform. It only implements a small set of transform types (like GBK/windowing); anything else raises RuntimeError. This means the pipeline contains a transform the trivial runner cannot simulate.
Solutions
- Run the pipeline with a real runner (DirectRunner, FlinkRunner, DataflowRunner) instead of TrivialRunner
- Check which transform_id/URN is unsupported and rewrite that stage using supported transforms (e.g. plain ParDo/GBK)
- Update/extend apache_beam: newer versions of trivial_runner support more URNs
- If intentional, implement the missing branch in TrivialRunner.execute_transform for that URN
Example fix
// before pipeline.run(runner=TrivialRunner()) // after pipeline.run(runner=DirectRunner()) # full transform support
Defensive patterns
Strategy: validation
Validate before calling
SUPPORTED_URNS = {'beam:transform:group_by_key', 'beam:transform:pardo'}
for t in pipeline.proto.components.transforms.values():
urn = t.spec.urn
if urn and urn not in SUPPORTED_URNS:
print('Unsupported by TrivialRunner:', t.unique_name, urn)
# use DirectRunner if any unsupported URN is found Try / catch
try:
pipeline.run(runner=TrivialRunner()).wait_until_finish()
except RuntimeError as e:
if 'Unsupported transform' in str(e):
logging.warning('TrivialRunner unsupported; falling back to DirectRunner')
pipeline.run(runner=DirectRunner())
else:
raise Prevention
- Use TrivialRunner only for pipelines limited to the transforms it supports
- Default to DirectRunner for local testing
- Check the transform URNs in the pipeline proto before choosing a runner
- Keep apache_beam updated so more URNs are supported
When it happens
Trigger: Calling beam.pipeline.run() with runner=TrivialRunner (or run_portable_pipeline) on a pipeline containing transforms outside the supported set (e.g. custom composite URNs, side inputs, SDF) — anything falling into the else branch at trivial_runner.py:128.
Common situations: Using TrivialRunner to smoke-test a pipeline that uses transforms unsupported by the trivial runner; running a portable pipeline locally with an oversimplified runner; a Beam SDK change added a transform type the trivial runner doesn't handle yet.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Google Cloud Dataflow runner not available, please install…
- Runner is not a PipelineRunner object or the name of a…
- Unexpected data type
- Unexpected pipeline runner
- A BigQuery table or a query must be specified
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/0fe3a77eb8af9294.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/runners/trivial_runner.py:128
output_pcoll_id,
sum([
execution_state.get_pcollection_contents(pc)
for pc in transform_proto.inputs.values()
], []))
elif transform_proto.spec.urn == common_urns.executable_stage:
# This is a collection of user DoFns.
self.execute_executable_stage(transform_proto, execution_state)
elif transform_proto.spec.urn == common_urns.primitives.GROUP_BY_KEY.urn:
# Execute the grouping operation.
self.group_by_key_and_window(
only_element(transform_proto.inputs.values()),
only_element(transform_proto.outputs.values()),
execution_state)
else:
raise RuntimeError(
f"Unsupported transform {transform_id}"
" of type {transform_proto.spec.urn}")
def execute_executable_stage(self, transform_proto, execution_state):
# Stage here is like a mini pipeline, with PTransforms, PCollections, etc.
# inside of it.
stage = beam_runner_api_pb2.ExecutableStagePayload.FromString(
transform_proto.spec.payload)
if stage.side_inputs:
# To support these we would need to make the side input PCollections
# available over the state API before processing this bundle.
raise NotImplementedError()
# This is the set of transforms that were fused together.
stage_transforms = {
id: stage.components.transforms[id]
for id in stage.transforms
}View on GitHub (pinned to 12126d8942)