pola-rs/polars · error · ComputeError

can't pass a Series with missing data to a generalized…

Error message

can't pass a Series with missing data to a generalized ufunc, as it might give unexpected results. See https://docs.pola.rs/user-guide/expressions/missing-data/ for suggestions on how to remove or fill in missing data.

What it means

Generalized numpy ufuncs (gufuncs, e.g. with signature '(n)->(n)') operate over the entire array, so nulls in the input Series would corrupt or propagate incorrectly through the whole computation. Polars refuses to pass a Series containing nulls to such a ufunc and raises ComputeError.

Solutions

  1. Remove nulls first: srs.drop_nulls()
  2. Fill nulls: srs.fill_null(0) (or an appropriate value)
  3. Filter to non-null rows before calling the ufunc

Example fix

// before
np.gufunc_like(srs)
// after
np.gufunc_like(srs.drop_nulls())
Defensive patterns

Strategy: validation

Validate before calling

if srs.has_nulls():
    srs = srs.drop_nulls()  # or fill_null(...)

Try / catch

try:
    out = gufunc(srs)
except pl.exceptions.ComputeError:
    out = gufunc(srs.drop_nulls())

Prevention

When it happens

Trigger: Applying a generalized ufunc via np.apply/ufunc dispatch (Series.__array_ufunc__ with is_generalized_ufunc=True) while self.has_nulls() is True, e.g. np.matmul-style gufuncs or np.vectorize with signature containing '->' shapes.

Common situations: Data loaded from files with missing values passed to a gufunc; forgetting to drop_nulls()/fill_null() after joins or parsing.

Related errors


AI-assisted analysis of pola-rs/polars@fe841f959e (2026-09-18). Data as JSON: /api/errors/9affb2181372517e. Report an issue: GitHub.

Appendix: source

Thrown at py-polars/src/polars/series/series.py:1568

                    dtype_char_minimum = dtype_ufunc
                    break

            # Override minimum dtype if requested.
            dtype_char = (
                np.dtype(kwargs.pop("dtype")).char
                if "dtype" in kwargs
                else dtype_char_minimum
            )

            # Only generalized ufuncs have a signature set:
            is_generalized_ufunc = bool(ufunc.signature)

            if is_generalized_ufunc:
                # Generalized ufuncs will operate on the whole array, so
                # missing data can corrupt the results.
                if self.has_nulls():
                    msg = "can't pass a Series with missing data to a generalized ufunc, as it might give unexpected results. See https://docs.pola.rs/user-guide/expressions/missing-data/ for suggestions on how to remove or fill in missing data."
                    raise ComputeError(msg)
                # If the input and output are the same size, e.g. "(n)->(n)" we
                # can allocate ourselves and save a copy. If they're different,
                # we let the ufunc do the allocation, since only it knows the
                # output size.
                assert ufunc.signature is not None  # pacify MyPy
                ufunc_input, ufunc_output = ufunc.signature.split("->")
                if ufunc_output == "()":
                    # If the result a scalar, just let the function do its
                    # thing, no need for any song and dance involving
                    # allocation:
                    return ufunc(*args, dtype=dtype_char, **kwargs)
                else:
                    allocate_output = ufunc_input == ufunc_output
            else:
                allocate_output = True

            f = get_ffi_func("apply_ufunc_<>", numpy_char_code_to_dtype(dtype_char), s)

View on GitHub (pinned to fe841f959e)