apache/beam · error · NotImplementedError

Passing a deferred series to round() is not supported, pleas

Error message

Passing a deferred series to round() is not supported, please use a concrete pd.Series instance or a dictionary

What it means

DeferredFrame.round() rejects a deferred (Beam) Series as the decimals argument. Beam's partitioning model cannot align a distributed rounding spec with the frame, so it requires a concrete pandas Series or a plain dict mapping column names to decimal places.

Source

Thrown at sdks/python/apache_beam/dataframe/frames.py:3736

        expressions.ComputedExpression(
            'rename',
            lambda df: df.rename(**kwargs),
            [self._expr],
            proxy=proxy,
            preserves_partition_by=preserves_partition_by,
            requires_partition_by=requires_partition_by))

  rename_axis = frame_base._elementwise_method('rename_axis', base=pd.DataFrame)

  @frame_base.with_docs_from(pd.DataFrame)
  @frame_base.args_to_kwargs(pd.DataFrame)
  @frame_base.populate_defaults(pd.DataFrame)
  def round(self, decimals, *args, **kwargs):

    if isinstance(decimals, frame_base.DeferredFrame):
      # Disallow passing a deferred Series in, our current partitioning model
      # prevents us from using it correctly.
      raise NotImplementedError("Passing a deferred series to round() is not "
                                "supported, please use a concrete pd.Series "
                                "instance or a dictionary")

    return frame_base.DeferredFrame.wrap(
        expressions.ComputedExpression(
            'round',
            lambda df: df.round(decimals, *args, **kwargs),
            [self._expr],
            requires_partition_by=partitionings.Arbitrary(),
            preserves_partition_by=partitionings.Index()
        )
    )

  select_dtypes = frame_base._elementwise_method('select_dtypes',
                                                 base=pd.DataFrame)

  @frame_base.with_docs_from(pd.DataFrame)
  @frame_base.args_to_kwargs(pd.DataFrame)

View on GitHub (pinned to 12126d8942)

Solutions

  1. Pass a plain dict like {'col_a': 2, 'col_b': 0}
  2. Materialize the decimals series with .to_pandas() before passing it
  3. Use pandas series computed locally for the rounding spec

Example fix

// before
df.beam.round(spec.beam)
// after
df.beam.round({'price': 2, 'qty': 0})  # or spec.beam.to_pandas()
Defensive patterns

Strategy: type-guard

Validate before calling

if isinstance(decimals, frame_base.DeferredFrame):
    decimals = decimals.to_pandas()

Type guard

def is_valid_decimals(d):
    return isinstance(d, (int, dict, pd.Series)) and not isinstance(d, frame_base.DeferredFrame)

Try / catch

try:
    out = dframe.round({'a': 2})
except NotImplementedError:
    out = dframe.round(decimals.to_pandas())

Prevention

When it happens

Trigger: Calling df.beam.round(decimals_series.beam) where decimals is a DeferredSeries instead of a pd.Series or dict

Common situations: Keeping per-column precision specs as a Beam Series and passing it straight into round()

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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