apache/beam · error · ValueError

Only one of expansion_service

Error message

Only one of expansion_service (%s) or classpath (%s) may be provided.

What it means

JavaExternalTransform.__init__ got both an explicit expansion_service and a classpath; the two are mutually exclusive ways to locate the Java transform (remote service vs. locally started service from jars), so passing both is rejected.

Solutions

  1. Pass only classpath jars and let Beam start the service locally
  2. Or pass only expansion_service (e.g. 'localhost:8097') and drop classpath
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at sdks/python/apache_beam/transforms/external.py:617 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at sdks/python/apache_beam/transforms/external.py:617

  One builds these transforms just as one would in Java, e.g.::

      transform = JavaExternalTransform('fully.qualified.ClassName'
          )(contructorArg, ... ).builderMethod(...)

  or::

      JavaExternalTransform('fully.qualified.ClassName').staticConstructor(
          ...).builderMethod1(...).builderMethod2(...)

  :param class_name: fully qualified name of the java class
  :param expansion_service: (Optional) an expansion service to use.  If none is
      provided, a default expansion service will be started.
  :param classpath: (Optional) A list paths to additional jars to place on the
      expansion service classpath.
  """
  def __init__(self, class_name, expansion_service=None, classpath=None):
    if expansion_service and classpath:
      raise ValueError(
          f'Only one of expansion_service ({expansion_service}) '
          f'or classpath ({classpath}) may be provided.')
    self._payload_builder = JavaClassLookupPayloadBuilder(class_name)
    self._classpath = classpath
    self._expansion_service = expansion_service
    # Beam explicitly looks for following attributes. Hence adding
    # 'None' values here to prevent '__getattr__' from being called.
    self.inputs = None
    self._fn_api_payload = None

  def __call__(self, *args, **kwargs):
    self._payload_builder.with_constructor(*args, **kwargs)
    return self

  def __getattr__(self, name):
    # Don't try to emulate special methods.
    if name.startswith('__') and name.endswith('__'):
      return super().__getattr__(name)

View on GitHub (pinned to 12126d8942)