apache/beam · error · ValueError

cannot specify both "expression" and "callable

Error message

{transform_name} cannot specify both "expression" and "callable"

What it means

_check_mapping_arguments enforces mutually exclusive definition styles: an inline expression and a callable cannot both be given. This ValueError fires when both 'expression' and 'callable' are truthy in the transform configuration.

Solutions

  1. Remove the `expression` if you intend to use a callable.
  2. Remove the `callable` if you intend to use an inline expression.
  3. Check YAML anchors/overrides that may merge both keys unintentionally.
  4. Pick one definition style per field.

Example fix

# before
config:
  expression: "x + 1"
  callable: my_func
# after
config:
  expression: "x + 1"
Defensive patterns

Strategy: validation

Validate before calling

assert not (config.get('expression') and config.get('callable')), 'choose expression OR callable'

Prevention

When it happens

Trigger: Configuring a mapping transform with both an `expression` string and a `callable` option simultaneously, through _as_callable.

Common situations: Merging two transform configs; switching from inline expression to a callable and forgetting to delete the expression; YAML anchors accidentally merging both fields.

Related errors


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

Appendix: source

Thrown at sdks/python/apache_beam/yaml/yaml_mapping.py:171

  if base_type == 'MapToFields':
    for field, value in list(config.get('fields', {}).items()):
      validate_generic_expression(value, input_fields, True, field)

  elif base_type in _str_expression_fields:
    param = _str_expression_fields[base_type]
    validate_generic_expression(
        config.get(param), input_fields, base_type == 'Filter', param)


def _check_mapping_arguments(
    transform_name, expression=None, callable=None, name=None, path=None):
  # Argument checking
  if not expression and not callable and not path and not name:
    raise ValueError(
        f'{transform_name} must specify either "expression", "callable", '
        f'or both "path" and "name"')
  if expression and callable:
    raise ValueError(
        f'{transform_name} cannot specify both "expression" and "callable"')
  if (expression or callable) and (path or name):
    raise ValueError(
        f'{transform_name} cannot specify "expression" or "callable" with '
        f'"path" or "name"')
  if path and not name:
    raise ValueError(f'{transform_name} cannot specify "path" without "name"')
  if name and not path:
    raise ValueError(f'{transform_name} cannot specify "name" without "path"')


_THREAD_LOCAL_JS_CACHE = threading.local()


class _JsFunctionWrapper:
  def __init__(self, source_code, entrypoint_name):
    self.source_code = source_code
    self.entrypoint_name = entrypoint_name

View on GitHub (pinned to 12126d8942)