apache/beam · error · WontImplementError

others must be None, DeferredSeries, or list[DeferredSeries]

Error message

others must be None, DeferredSeries, or list[DeferredSeries] (encountered {type(others)}). Other types are not supported because they make this operation sensitive to the order of the data.

What it means

DeferredStringMethods.str.cat raises WontImplementError when `others` is neither None, a DeferredSeries, nor a list of DeferredSeries. Passing raw Python string lists (or other objects) would concatenate in a way that depends on the order/count of elements relative to rows, making the operation order-sensitive in Beam's deferred model.

Solutions

  1. Convert each list/pandas Series into a deferred Beam Series (e.g. via the pipeline's read or from a DataFrame column) and pass those as `others`.
  2. Pass others=None and use only the `sep` parameter if you just need a separator join of the series itself.
  3. Build the concatenation with the '+' operator on multiple deferred Series instead of str.cat.
  4. Use str.cat with a list of DeferredSeries wrapped individually rather than a nested/foreign collection.

Example fix

// before
result = s.str.cat(['x', 'y'], sep='-')

// after
other = pd.Series(['x', 'y']).to_frame('c')['c']  # as a deferred series in the pipeline
result = s.str.cat(other, sep='-')
Defensive patterns

Strategy: type-guard

Validate before calling

if others is not None:
    seq = others if isinstance(others, list) else [others]
    for o in seq:
        if not isinstance(o, DeferredFrame):
            raise ValueError("str.cat others must be DeferredSeries")

Type guard

def valid_cat_others(others):
    if others is None:
        return True
    items = others if isinstance(others, list) else [others]
    return all(isinstance(o, frame_base.DeferredFrame) for o in items)

Try / catch

try:
    joined = s.str.cat(others)
except apachebeam.WontImplementError:
    joined = s + sep + other_deferred_series

Prevention

When it happens

Trigger: s.str.cat(['a', 'b']), s.str.cat(other_series_list_with_plain_lists), or passing a pandas Series/list of strings as `others` to str.cat on a deferred Beam Series.

Common situations: Copying pandas str.cat examples that join with literal separator lists; mixing plain pandas Series with deferred Beam Series; building a join string from constants.

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


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

Appendix: source

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

          "string, so it requires collecting all data on a single node."
      ))
      func = lambda df: df.str.cat(join=join, **kwargs)
      args = [self._expr]

    elif (isinstance(others, frame_base.DeferredBase) or
         (isinstance(others, list) and
          all(isinstance(other, frame_base.DeferredBase) for other in others))):

      if isinstance(others, frame_base.DeferredBase):
        others = [others]

      requires = partitionings.Index()
      def func(*args):
        return args[0].str.cat(others=args[1:], join=join, **kwargs)
      args = [self._expr] + [other._expr for other in others]

    else:
      raise frame_base.WontImplementError(
          "others must be None, DeferredSeries, or list[DeferredSeries] "
          f"(encountered {type(others)}). Other types are not supported "
          "because they make this operation sensitive to the order of the "
          "data.", reason="order-sensitive")

    return frame_base.DeferredFrame.wrap(
        expressions.ComputedExpression(
            'cat',
            func,
            args,
            requires_partition_by=requires,
            preserves_partition_by=partitionings.Arbitrary()))

  @frame_base.with_docs_from(pd.Series.str)
  @frame_base.args_to_kwargs(pd.Series.str)
  def repeat(self, repeats):
    """``repeats`` must be an ``int`` or a :class:`DeferredSeries`. Lists are
    not supported because they make this operation order-sensitive."""

View on GitHub (pinned to 12126d8942)