apache/beam · error · ValueError

Expansion service with target

Error message

Expansion service with target '{target}' does not specify any default destinations.

What it means

gen_xlang_wrappers.py reads the expansion-services YAML config and, for each service entry, requires a 'destinations' mapping of SDK to output directory. A service without that key cannot have wrappers generated, so generate_transforms_config raises ValueError naming the service's gradle target.

Solutions

  1. Add a 'destinations' mapping (SDK -> directory) to the offending service entry in the expansion services YAML.
  2. Match the destinations format of existing entries and confirm each destination directory exists under sdks/python.
  3. Re-run gen_xlang_wrappers.py.

Example fix

// before (services yaml)
- gradle_target: :sdks:java:io:expansion-service:shadowJar
// after
- gradle_target: :sdks:java:io:expansion-service:shadowJar
  destinations:
    python: sdks/python/apache_beam/transforms/xlang_io
Defensive patterns

Strategy: validation

Validate before calling

for svc in yaml.safe_load(open(services_yaml)):
    assert 'destinations' in svc, f"service {svc.get('gradle_target')} needs a 'destinations' map"

Type guard

def has_destinations(svc):
    return isinstance(svc, dict) and isinstance(svc.get('destinations'), dict) and bool(svc['destinations'])

Try / catch

try:
    generate_transforms_config(services_yaml, ...)
except ValueError as e:
    if 'does not specify any default destinations' in str(e):
        print('Add destinations to the offending expansion service entry')

Prevention

When it happens

Trigger: An expansion service entry in the input services YAML lacks the required 'destinations' field while running the xlang wrapper generation script.

Common situations: Contributors registering a new expansion service forget to add default destinations; YAML restructuring accidentally drops the key.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at sdks/python/gen_xlang_wrappers.py:126

    - gradle_target: 'sdks:java:io:expansion-service:shadowJar'
      destinations:
        python: 'apache_beam/io'
      skip_transforms:
        - 'beam:schematransform:org.apache.beam:some_transform:v1'
  """
  from apache_beam.transforms.external import BeamJarExpansionService
  from apache_beam.transforms.external_transform_provider import ExternalTransform
  from apache_beam.transforms.external_transform_provider import ExternalTransformProvider

  transform_list: list[dict[str, Any]] = []

  with open(input_services) as f:
    services = yaml.safe_load(f)
  for service in services:
    target = service['gradle_target']

    if "destinations" not in service:
      raise ValueError(
          f"Expansion service with target '{target}' does not "
          "specify any default destinations.")
    service_destinations: dict[str, str] = service['destinations']
    for sdk, dest in service_destinations.items():
      validate_sdks_destinations(sdk, dest, target)

    transforms_to_skip = service.get('skip_transforms', [])

    # use dynamic provider to discover and populate wrapper details
    provider = ExternalTransformProvider(BeamJarExpansionService(target))
    discovered: dict[str, ExternalTransform] = provider.get_all()
    for identifier in sorted(discovered.keys()):
      wrapper = discovered[identifier]
      if identifier in transforms_to_skip:
        continue

      transform_destinations = service_destinations.copy()

View on GitHub (pinned to 12126d8942)