pola-rs/polars · error · ValueError

expected at least one Series in 'coalesce' if 'eager=True'

Error message

expected at least one Series in 'coalesce' if 'eager=True'

What it means

`pl.coalesce(exprs, *more_exprs, eager=True)` filters the inputs for Series to build the backing DataFrame; if none of the inputs is a `pl.Series`, ValueError is raised. Strings/Exprs require lazy mode or at least one Series in eager mode.

Solutions

  1. Pass Series: `pl.coalesce([df["a"], df["b"]], eager=True)`
  2. Use lazy form: `df.select(pl.coalesce("a", "b"))`
  3. Remove `eager=True` if lazy was intended

Example fix

// before
pl.coalesce(["a", "b"], eager=True)
// after
pl.coalesce([df["a"], df["b"]], eager=True)
Defensive patterns

Strategy: type-guard

Validate before calling

def coalesce_eager(*exprs):
    if not any(isinstance(e, pl.Series) for e in exprs):
        raise TypeError("coalesce(eager=True) needs at least one pl.Series")
    return pl.coalesce(list(exprs), eager=True)

Type guard

def coalesce_eager_ok(exprs): return any(isinstance(e, pl.Series) for e in exprs)

Try / catch

try:
    return pl.coalesce(exprs, eager=True)
except ValueError:
    return df.select(pl.coalesce(*exprs))

Prevention

When it happens

Trigger: `pl.coalesce(["a", "b"], eager=True)` — all string column names with eager=True.

Common situations: Using eager mode with column-name strings; porting lazy code to eager without converting columns via `df["col"]`.

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 pola-rs/polars@fe841f959e (2026-09-18). Data as JSON: /api/errors/6b4638d1e8836565. Report an issue: GitHub.

Appendix: source

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

    │ null ┆ null ┆ null ┆ 10.0 │
    └──────┴──────┴──────┴──────┘

    >>> s1 = pl.Series("a", [None, 2, None])
    >>> s2 = pl.Series("b", [1, None, 3])
    >>> pl.coalesce(s1, s2, eager=True)
    shape: (3,)
    Series: 'a' [i64]
    [
        1
        2
        3
    ]
    """
    if eager:
        exprs = [exprs, *more_exprs]
        if not (series := [e for e in exprs if isinstance(e, pl.Series)]):
            msg = "expected at least one Series in 'coalesce' if 'eager=True'"
            raise ValueError(msg)

        exprs = [(e.name if isinstance(e, pl.Series) else e) for e in exprs]
        return pl.DataFrame(series).select(coalesce(exprs, eager=False)).to_series()
    else:
        exprs = parse_into_list_of_expressions(exprs, *more_exprs)
        return wrap_expr(plr.coalesce(exprs))


@overload
def from_epoch(column: str | Expr, time_unit: EpochTimeUnit = ...) -> Expr: ...


@overload
def from_epoch(
    column: Series | Sequence[int | float], time_unit: EpochTimeUnit = ...
) -> Series: ...

View on GitHub (pinned to fe841f959e)