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
- Add a 'destinations' mapping (SDK -> directory) to the offending service entry in the expansion services YAML.
- Match the destinations format of existing entries and confirm each destination directory exists under sdks/python.
- 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
- Validate the services YAML schema in CI before running generation.
- Copy the structure of existing service entries when registering new ones.
- Keep a JSON schema for the expansion services config.
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
- specifies a destination for an invalid SDK: ' '. The…
- specifies an invalid destination ' '. Please make sure the…
- Missing inputs for transform at
- Missing transform type
- 'No available provider for type %r at
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)