apache/beam · error · ValueError

f'Ambiguous transform at line

Error message

f'Ambiguous transform at line {SafeLineLoader.get_line(transform_name)}: {transform_name}'

What it means

LightweightScope.get_transform_id resolves a transform name to its unique id. When the pipeline YAML contains more than one transform sharing the same name (or type label), the name cannot be resolved unambiguously, so Beam raises this ValueError instead of silently picking one.

Solutions

  1. Give every transform in the pipeline a unique `name:` field.
  2. Find the duplicate by searching the YAML for the reported name.
  3. If the name was meant to select an output, reference it as `TransformName.output_tag` instead of relying on the transform name alone.
  4. Use transform ids/line numbers from the message to disambiguate which blocks collide.

Example fix

# before
- name: parse
  type: MapToFields
  ...
- name: parse
  type: MapToFields
  ...
# after
- name: parse_records
  type: MapToFields
  ...
- name: parse_errors
  type: MapToFields
  ...
Defensive patterns

Strategy: validation

Validate before calling

import collections
names = [t.get('name') for t in pipeline['transforms'] if t.get('name')]
dups = [n for n, c in collections.Counter(names).items() if c > 1]
if dups:
    raise ValueError(f'Duplicate transform names: {dups}')

Type guard

def is_unambiguous(specs, name):
    matches = [t for t in specs if t.get('name') == name]
    return len(matches) == 1

Try / catch

try:
    tid = scope.get_transform_id(name)
except ValueError as e:
    if 'Ambiguous transform' in str(e):
        candidates = [t for t in specs if t.get('name') == name]
        tid = candidates[0]['__uuid__']

Prevention

When it happens

Trigger: Referencing a transform by name in an `input:` reference, via `get_transform_spec`, `followers`, `get_pcollection`, `get_outputs`, or `best_provider`, when two or more transforms in the pipeline spec declare the same `name` (or the same `type` string).

Common situations: Copy-pasting a transform block in the YAML without renaming it; generated pipelines that reuse names; using a bare type like `ReadFromBigQuery` as a reference while several transforms of that type exist.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


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

Appendix: source

Thrown at sdks/python/apache_beam/yaml/yaml_transform.py:168

  def get_transform_id_and_output_name(self, name):
    if '.' in name:
      transform_name, output = name.rsplit('.', 1)
    else:
      transform_name, output = name, None
    return self.get_transform_id(transform_name), output

  def get_transform_id(self, transform_name):
    if transform_name in self._transforms_by_uuid:
      return transform_name
    else:
      candidates = self._uuid_by_name[transform_name]
      if not candidates:
        raise ValueError(
            f'Unknown transform at line '
            f'{SafeLineLoader.get_line(transform_name)}: {transform_name}')
      elif len(candidates) > 1:
        raise ValueError(
            f'Ambiguous transform at line '
            f'{SafeLineLoader.get_line(transform_name)}: {transform_name}')
      else:
        return only_element(candidates)

  def get_transform_spec(self, transform_name_or_id):
    return self._transforms_by_uuid[self.get_transform_id(transform_name_or_id)]


class Scope(LightweightScope):
  """To look up PCollections (typically outputs of prior transforms) by name."""
  def __init__(
      self,
      root,
      inputs: Mapping[str, Any],
      transforms: Iterable[dict],
      providers: Mapping[str, Iterable[yaml_provider.Provider]],
      input_providers: Iterable[yaml_provider.Provider]):

View on GitHub (pinned to 12126d8942)