apache/beam · error · WontImplementError

append() was removed in Pandas 2.0.

Error message

append() was removed in Pandas 2.0.

What it means

DeferredSeries.append is a deprecated wrapper: pandas removed Series.append in 2.0, so Beam's deferred implementation raises WontImplementError whenever the installed pandas is >= 2.0. The operation must be replaced with pandas.concat, which Beam DataFrames supports.

Solutions

  1. Replace append with pd.concat: pd.concat([s, to_append]) (works in both deferred and eager pandas).
  2. Pin pandas<2.0 only as a short-term stopgap.
  3. Update code samples/docs that reference Series.append.

Example fix

// before
combined = s.append(to_append)
// after
combined = pd.concat([s, to_append])
Defensive patterns

Strategy: try-catch

Validate before calling

import pandas as pd
PD_VERSION = tuple(int(p) for p in pd.__version__.split('.')[:2])
if PD_VERSION >= (2, 0) and hasattr(s, 'append'):
    raise DeprecationWarning("Series.append removed in pandas 2.0; use pd.concat")

Try / catch

from apache_beam.dataframe import frame_base
try:
    combined = s.append(to_append)
except frame_base.WontImplementError:
    combined = pd.concat([s, to_append])

Prevention

When it happens

Trigger: Calling s.append(other) on a DeferredSeries while pandas >= 2.0 is installed.

Common situations: Upgrading pandas from 1.x to 2.x in a Beam pipeline; following pre-2.0 pandas tutorials; requirements.txt floating to pandas 2.x.

Understand the failure class

Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.

Related errors


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

Appendix: source

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

  @frame_base.with_docs_from(pd.Series)
  def keys(self):
    return self.index

  # Series.T == transpose. Both are a no-op
  T = frame_base._elementwise_method('T', base=pd.Series)
  transpose = frame_base._elementwise_method('transpose', base=pd.Series)
  shape = property(
      frame_base.wont_implement_method(
          pd.Series, 'shape', reason="non-deferred-result"))

  @frame_base.with_docs_from(pd.Series, removed_method=PD_VERSION >= (2, 0))
  @frame_base.args_to_kwargs(pd.Series, removed_method=PD_VERSION >= (2, 0))
  @frame_base.populate_defaults(pd.Series, removed_method=PD_VERSION >= (2, 0))
  def append(self, to_append, ignore_index, verify_integrity, **kwargs):
    """``ignore_index=True`` is not supported, because it requires generating an
    order-sensitive index."""
    if PD_VERSION >= (2, 0):
      raise frame_base.WontImplementError('append() was removed in Pandas 2.0.')
    if not isinstance(to_append, DeferredSeries):
      raise frame_base.WontImplementError(
          "append() only accepts DeferredSeries instances, received " +
          str(type(to_append)))
    if ignore_index:
      raise frame_base.WontImplementError(
          "append(ignore_index=True) is order sensitive because it requires "
          "generating a new index based on the order of the data.",
          reason="order-sensitive")

    if verify_integrity:
      # We can verify the index is non-unique within index partitioned data.
      requires = partitionings.Index()
    else:
      requires = partitionings.Arbitrary()

    return frame_base.DeferredFrame.wrap(
        expressions.ComputedExpression(

View on GitHub (pinned to 12126d8942)