{"record":{"id":"6b4638d1e8836565","repo":"pola-rs/polars","slug":"expected-at-least-one-series-in-coalesce-if-eag","errorCode":null,"errorMessage":"expected at least one Series in 'coalesce' if 'eager=True'","messagePattern":"expected at least one Series in 'coalesce' if 'eager=True'","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/functions/lazy.py","lineNumber":2570,"sourceCode":"    │ null ┆ null ┆ null ┆ 10.0 │\n    └──────┴──────┴──────┴──────┘\n\n    >>> s1 = pl.Series(\"a\", [None, 2, None])\n    >>> s2 = pl.Series(\"b\", [1, None, 3])\n    >>> pl.coalesce(s1, s2, eager=True)\n    shape: (3,)\n    Series: 'a' [i64]\n    [\n        1\n        2\n        3\n    ]\n    \"\"\"\n    if eager:\n        exprs = [exprs, *more_exprs]\n        if not (series := [e for e in exprs if isinstance(e, pl.Series)]):\n            msg = \"expected at least one Series in 'coalesce' if 'eager=True'\"\n            raise ValueError(msg)\n\n        exprs = [(e.name if isinstance(e, pl.Series) else e) for e in exprs]\n        return pl.DataFrame(series).select(coalesce(exprs, eager=False)).to_series()\n    else:\n        exprs = parse_into_list_of_expressions(exprs, *more_exprs)\n        return wrap_expr(plr.coalesce(exprs))\n\n\n@overload\ndef from_epoch(column: str | Expr, time_unit: EpochTimeUnit = ...) -> Expr: ...\n\n\n@overload\ndef from_epoch(\n    column: Series | Sequence[int | float], time_unit: EpochTimeUnit = ...\n) -> Series: ...\n\n","sourceCodeStart":2552,"sourceCodeEnd":2588,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/functions/lazy.py#L2552-L2588","documentation":"Raised by polars.coalesce when eager=True yet none of the provided exprs is a pl.Series. The eager path builds a DataFrame from the Series inputs (using each Series' name) and runs the lazy coalesce on it, so it needs at least one materialized Series to anchor execution.","triggerScenarios":"pl.coalesce([pl.col('a'), pl.col('b')], eager=True); pl.coalesce('a', 'b', eager=True) with string column names; mixing only Exprs/strings with eager=True.","commonSituations":"Expecting eager=True to evaluate against 'the current DataFrame' (there is none in this API); upgrading scripts where coalesce was previously used only inside select; passing a list of column-name strings.","solutions":["Pass at least one Series, e.g. pl.coalesce(df['a'], df['b'], eager=True)","Evaluate lazily instead: df.select(pl.coalesce(['a', 'b']))","For filling nulls across columns in a DataFrame, use df.select(pl.coalesce(...)) or df.fill_nan/fill_null as appropriate"],"exampleFix":"// before\npl.coalesce([pl.col('a'), pl.col('b')], eager=True)\n// after\npl.coalesce(df['a'], df['b'], eager=True)\n# or:\ndf.select(pl.coalesce(['a', 'b']))","handlingStrategy":"validation","validationCode":"import polars as pl\n\nif eager and not any(isinstance(e, pl.Series) for e in ([exprs, *more_exprs] if not isinstance(exprs, (list, tuple)) else [*exprs, *more_exprs])):\n    raise ValueError('coalesce(eager=True) needs at least one pl.Series')","typeGuard":"def has_at_least_one_series(exprs) -> bool:\n    return any(isinstance(e, pl.Series) for e in exprs)","tryCatchPattern":"try:\n    out = pl.coalesce(exprs, eager=True)\nexcept ValueError:\n    out = df.select(pl.coalesce(exprs)).to_series()","preventionTips":["Pass Series objects (df['a']) rather than column names when using eager APIs","Wrap eager coalesce in a helper that validates inputs first"],"tags":["polars","eager-execution","coalesce","type-validation"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}