pola-rs/polars · error · NotImplementedError

Only call is implemented not {method}

Error message

Only call is implemented not {method}

What it means

Expr implements NumPy's ufunc protocol (via __array_ufunc__) only for plain calls, where method == '__call__'. NumPy ufunc methods — reduce, accumulate, outer, reduceat, at — route through the same protocol with a different method string and raise NotImplementedError. Elementwise usage like np.sqrt(expr) works; np.add.reduce(expr) does not.

Source

Thrown at py-polars/src/polars/expr/expr.py:472

        other_expr = parse_into_expression(other)
        return wrap_expr(other_expr.xor_(self._pyexpr))

    def __getstate__(self) -> bytes:
        return self._pyexpr.__getstate__()

    def __setstate__(self, state: bytes) -> None:
        # Initialize with a dummy
        tmp = F.lit(0)._pyexpr
        tmp.__setstate__(state)
        self._pyexpr = tmp

    def __array_ufunc__(
        self, ufunc: Callable[..., Any], method: str_, *inputs: Any, **kwargs: Any
    ) -> Expr:
        """Numpy universal functions."""
        if method != "__call__":
            msg = f"Only call is implemented not {method}"
            raise NotImplementedError(msg)
        # Numpy/Scipy ufuncs have signature None but numba signatures always exists.
        is_custom_ufunc = getattr(ufunc, "signature") is not None  # noqa: B009
        if is_custom_ufunc is True:
            msg = (
                "Native numpy ufuncs are dispatched using `map_batches(ufunc, is_elementwise=True)` which "
                "is safe for native Numpy and Scipy ufuncs but custom ufuncs in a group_by "
                "context won't be properly grouped. Custom ufuncs are dispatched with is_elementwise=False. "
                f"If {ufunc.__name__} needs elementwise then please use map_batches directly."
            )
            warnings.warn(
                msg,
                CustomUFuncWarning,
                stacklevel=find_stacklevel(),
            )
        if len(inputs) == 1 and len(kwargs) == 0:
            # if there is only 1 input then it must be an Expr for this func to
            # have been called. If there are no kwargs then call map_batches
            # directly on the ufunc

View on GitHub (pinned to df599052da)

Solutions

  1. Use native polars equivalents: .sum(), .cum_sum(), .dot() instead of reduce/accumulate/outer
  2. Call the ufunc directly for elementwise math: np.sqrt(expr) (dispatched via __call__)
  3. If a numpy reduction is truly required, wrap it: expr.map_batches(lambda s: np.add.reduce(s))

Example fix

# before
out = np.add.reduce(pl.col('a'))  # NotImplementedError

# after
out = pl.col('a').sum()
# or elementwise: out = np.sqrt(pl.col('a'))
Defensive patterns

Strategy: try-catch

Try / catch

try:
    out = np.add.reduce(expr)
except NotImplementedError:
    out = expr.sum()  # native reduction fallback

Prevention

When it happens

Trigger: np.add.reduce(pl.col('a')); np.multiply.accumulate(pl.col('a')); np.subtract.outer(e1, e2); any ufunc-method syntax applied to an Expr.

Common situations: Porting numpy reduction idioms (sum via np.add.reduce) to polars expressions; scipy/numba code that calls ufunc methods; np.vectorize-style wrappers.

Related errors


AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16). Data as JSON: /api/errors/0bec0750e682ce35. Report an issue: GitHub.