pola-rs/polars · error · ValueError

expected at least one Series in 'cov' inputs if 'eager=True'

Error message

expected at least one Series in 'cov' inputs if 'eager=True'

What it means

pl.cov(..., eager=True) builds a one-shot DataFrame from the Series inputs and returns the covariance as a scalar Series. If neither a nor b is a pl.Series (both are Exprs or bare column names) there is no data to compute over, so ValueError is raised before evaluation.

Source

Thrown at py-polars/src/polars/functions/lazy.py:1067

    ╞═════╪═════╡
    │ 3.0 ┆ 6.0 │
    └─────┴─────┘

    Eager evaluation:

    >>> s1 = pl.Series("a", [1, 8, 3])
    >>> s2 = pl.Series("b", [4, 5, 2])
    >>> pl.cov(s1, s2, eager=True)
    shape: (1,)
    Series: 'a' [f64]
    [
        3.0
    ]
    """
    if eager:
        if not (isinstance(a, pl.Series) or isinstance(b, pl.Series)):
            msg = "expected at least one Series in 'cov' inputs if 'eager=True'"
            raise ValueError(msg)

        frame = pl.DataFrame([e for e in (a, b) if isinstance(e, pl.Series)])
        exprs = ((e.name if isinstance(e, pl.Series) else e) for e in (a, b))
        return frame.select(cov(*exprs, eager=False, ddof=ddof)).to_series()
    else:
        a_pyexpr = parse_into_expression(a)
        b_pyexpr = parse_into_expression(b)
        return wrap_expr(plr.cov(a_pyexpr, b_pyexpr, ddof))


class _map_batches_wrapper:
    def __init__(
        self,
        function: Callable[[Sequence[Series]], Series | Any],
        *,
        returns_scalar: bool,
    ) -> None:
        self.function = function

View on GitHub (pinned to df599052da)

Solutions

  1. Pass Series: pl.cov(df['a'], df['b'], eager=True)
  2. Or evaluate in context: df.select(pl.cov('a', 'b')).item()
  3. Mixed Series + Expr is fine — the expression is evaluated against the Series' frame

Example fix

# before
pl.cov('a', 'b', eager=True)  # ValueError

# after
pl.cov(df['a'], df['b'], eager=True)
# or
df.select(pl.cov('a', 'b')).item()
Defensive patterns

Strategy: validation

Validate before calling

if eager and not (isinstance(a, pl.Series) or isinstance(b, pl.Series)):
    result = df.select(pl.cov(a, b, ddof=ddof)).item()
else:
    result = pl.cov(a, b, eager=eager, ddof=ddof)

Type guard

def has_series_input(a, b) -> bool:
    return isinstance(a, pl.Series) or isinstance(b, pl.Series)

Prevention

When it happens

Trigger: pl.cov('a', 'b', eager=True); pl.cov(pl.col('a'), pl.col('b'), eager=True) outside select; converting a df.select(pl.cov(...)) snippet into a standalone call with eager=True.

Common situations: Summary/statistics helpers that switched from context-based to eager evaluation; quick notebooks referencing columns by name only.

Related errors


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