apache/beam · error · TypeError
Field expression %r at
Error message
Field expression %r at %s must be a callable or a string.
What it means
Raised by apache_beam.transforms.core._expr_to_callable, a helper used by GroupBy to turn key/field expressions into callables. A field expression must either be a string naming an attribute of each element, or a callable taking the element and returning the key value. Anything else (int, dict, None, etc.) cannot be interpreted, so a TypeError is raised naming the offending expression and its position.
Solutions
- Pass attribute names as strings: beam.GroupBy('field_name') instead of beam.GroupBy(field_name).
- If the key is computed, pass a lambda/function: beam.GroupBy(lambda x: x.field).
- For multiple fields, pass multiple strings/callables: beam.GroupBy('a', 'b').
- Validate your expression list before constructing: all(isinstance(e, (str,)) or callable(e) for e in exprs).
Example fix
// before
import beam
result = pc | beam.GroupBy(field_id) # field_id = 7
// after
result = pc | beam.GroupBy('field_id') Defensive patterns
Strategy: type-guard
Validate before calling
def check_exprs(exprs):
assert all(isinstance(e, str) or callable(e) for e in exprs), 'GroupBy expressions must be str or callable' Type guard
def is_field_expr(e):
return isinstance(e, str) or callable(e) Prevention
- Always quote field names passed to GroupBy
- Use lambdas for computed keys
- Validate dynamic expression lists before building the transform
When it happens
Trigger: Passing a non-string, non-callable to GroupBy's field expressions, e.g. beam.GroupBy(42), GroupBy(None), GroupBy({'a': 1}), or a list of expressions where one element is not a str/callable.
Common situations: Typos such as GroupBy(a, b) passing raw variable names (values like 42) instead of strings 'a'; refactoring code that changed a lambda into a value; building expressions dynamically from config where a numeric field index is passed instead of a field name string.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Cannot specify both 'labels' and 'index'/'columns'
- dropna=False does not work as intended in the Beam…
- Names must be a collection, not a string
- Namespaces must be an iterable, not a string
- num_splits must be greater than or equal 0
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/7889e00488166a5f.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/transforms/core.py:3570
return common_urns.primitives.GROUP_BY_KEY.urn, None
@staticmethod
@PTransform.register_urn(common_urns.primitives.GROUP_BY_KEY.urn, None)
def from_runner_api_parameter(
unused_ptransform, unused_payload, unused_context):
return GroupByKey()
def runner_api_requires_keyed_input(self):
return True
def _expr_to_callable(expr, pos):
if isinstance(expr, str):
return lambda x: getattr(x, expr)
elif callable(expr):
return expr
else:
raise TypeError(
'Field expression %r at %s must be a callable or a string.' %
(expr, pos))
class GroupBy(PTransform):
"""Groups a PCollection by one or more expressions, used to derive the key.
`GroupBy(expr)` is roughly equivalent to
beam.Map(lambda v: (expr(v), v)) | beam.GroupByKey()
but provides several conveniences, e.g.
* Several arguments may be provided, as positional or keyword arguments,
resulting in a tuple-like key. For example `GroupBy(a=expr1, b=expr2)`
groups by a key with attributes `a` and `b` computed by applying
`expr1` and `expr2` to each element.
View on GitHub (pinned to 12126d8942)