apache/beam · error · WontImplementError
len(df) is not currently supported because it produces a…
Error message
len(df) is not currently supported because it produces a non-deferred result. Consider using df.length() instead.
What it means
len(df) on a DeferredDataFrame would have to compute the number of rows immediately, producing a concrete (non-deferred) scalar — which breaks the deferred-execution contract of the Beam DataFrame API. The API raises WontImplementError and points you to df.length(), which returns a deferred scalar expression integrated into the pipeline.
Solutions
- Use df.length() which returns a deferred expression; feed it into the pipeline or collect it via compute().
- If a concrete count is required, call beam.dataframe.compute(df.length()) (or to_pandas on the length expression) at a pipeline boundary.
- Replace `if len(df)` checks with logic that stays deferred, or restructure to avoid data-dependent control flow.
Example fix
// before n = len(df) // after n_expr = df.length() # deferred; compute() it if a concrete value is needed
Defensive patterns
Strategy: try-catch
Validate before calling
if isinstance(df, DeferredDataFrame):
n = df.length() # deferred
else:
n = len(df) Type guard
from apache_beam.dataframe.frames import DeferredDataFrame
def is_deferred_frame(obj) -> bool:
return isinstance(obj, DeferredDataFrame) Try / catch
try:
n = len(df)
except frame_base.WontImplementError:
n = beam.dataframe.compute(df.length()) Prevention
- Never use len() or truthiness checks on deferred frames
- Use df.length() for row counts
- Avoid data-dependent `if len(df):` control flow in pipelines
When it happens
Trigger: Calling len(df) or bool(df) (which uses __len__ for truthiness) on a DeferredDataFrame.
Common situations: Debug prints of row counts in notebooks; `if len(df) == 0:` guards ported from pandas; assertions in pipeline code converted from pandas to Beam.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Accessing a DeferredSeries with an iterator is sensitive to…
- Accessing an item by an integer key is order sensitive for…
- align(copy=False) is not supported because it might be an…
- align(method= ) is not supported because it is order…
- append(ignore_index=True) is order sensitive because it…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/4abf76894ee7e138.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/dataframe/frames.py:778
used in arithmetic with :class:`DeferredSeries` or
:class:`DeferredDataFrame` instances."""
lengths = expressions.ComputedExpression(
'get_lengths',
# Wrap scalar results in a Series for easier concatenation later
lambda df: pd.Series(len(df)),
[self._expr],
requires_partition_by=partitionings.Arbitrary(),
preserves_partition_by=partitionings.Singleton())
with expressions.allow_non_parallel_operations(True):
return frame_base.DeferredFrame.wrap(
expressions.ComputedExpression(
'sum_lengths', lambda lengths: lengths.sum(), [lengths],
requires_partition_by=partitionings.Singleton(),
preserves_partition_by=partitionings.Singleton()))
def __len__(self):
raise frame_base.WontImplementError(
"len(df) is not currently supported because it produces a non-deferred "
"result. Consider using df.length() instead.",
reason="non-deferred-result")
@property # type: ignore
@frame_base.with_docs_from(pd.DataFrame)
def empty(self):
empties = expressions.ComputedExpression(
'get_empties',
# Wrap scalar results in a Series for easier concatenation later
lambda df: pd.Series(df.empty),
[self._expr],
requires_partition_by=partitionings.Arbitrary(),
preserves_partition_by=partitionings.Singleton())
with expressions.allow_non_parallel_operations(True):
return frame_base.DeferredFrame.wrap(
expressions.ComputedExpression(View on GitHub (pinned to 12126d8942)