pola-rs/polars · error · TypeError
`map` with `returns_scalar=False` must return a Series…
Error message
`map` with `returns_scalar=False` must return a Series; found {qualified_type_name(rv)!r}.
If `returns_scalar` is set to `True`, a returned value can be a scalar value. What it means
The Python function passed to `Expr.map` is applied per group/window and, with `returns_scalar=False` (the default), must return a `pl.Series`. If it returns any other object (list, scalar, numpy array), the map callback raises TypeError. Scalars require explicitly setting `returns_scalar=True`.
Solutions
- Return a `pl.Series` from the mapped function
- Set `returns_scalar=True` if the function returns a single scalar value
- Use `map_batches` if you want batch semantics with flexible return handling
- Wrap non-Series results: `pl.Series(rv)`
Example fix
// before
pl.col("x").map(lambda s: s.sum())
// after
pl.col("x").map(lambda s: s.sum(), returns_scalar=True)
# or return a Series:
pl.col("x").map(lambda s: pl.Series([s.sum()])) Defensive patterns
Strategy: type-guard
Validate before calling
def mapped(fn, returns_scalar=False):
def wrapped(s):
rv = fn(s)
if not returns_scalar and not isinstance(rv, pl.Series):
raise TypeError("map function must return pl.Series or set returns_scalar=True")
return rv
return wrapped Type guard
def map_result_ok(rv, returns_scalar): return isinstance(rv, pl.Series) or returns_scalar
Try / catch
try:
out = df.select(pl.col("x").map(fn))
except TypeError:
out = df.select(pl.col("x").map(fn, returns_scalar=True)) Prevention
- Return pl.Series from map callbacks by default
- Set returns_scalar=True for aggregating callbacks
- Prefer map_batches for batch-style transforms
When it happens
Trigger: `df.select(pl.col("x").map(lambda s: s.sum()))` or a lambda returning `s.to_list()` / a plain value while `returns_scalar` is left False.
Common situations: Confusing `map` with `map_elements`; migrating from older `apply`; forgetting `returns_scalar=True` for aggregate-style callbacks; returning numpy arrays instead of Series.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- `arctan2` expected a `str` or `Expr` got a
- `arctan2` expected a `str` or `Expr` got a
- cannot convert Python type
- Expected Polars expression or object convertible to one, got
- expected Series in 'arg_where' if 'eager=True', got
AI-assisted analysis of pola-rs/polars@fe841f959e (2026-09-18).
Data as JSON: /api/errors/35c6275863dc5535.
Report an issue: GitHub.
Appendix: source
Thrown at py-polars/src/polars/functions/lazy.py:1088
try:
rv = self.function(slp, *args, **kwargs)
except TypeError as e:
if "unexpected keyword argument 'return_dtype'" in e.args[0]:
kwargs.pop("return_dtype")
rv = self.function(slp, *args, **kwargs)
else:
raise
if _check_for_numpy(rv) and isinstance(rv, np.ndarray):
rv = pl.Series(rv, dtype=return_dtype)
if isinstance(rv, pl.Series):
return rv._s
elif self.returns_scalar:
return pl.Series([rv], dtype=return_dtype)._s
else:
msg = f"`map` with `returns_scalar=False` must return a Series; found {qualified_type_name(rv)!r}.\n\nIf `returns_scalar` is set to `True`, a returned value can be a scalar value."
raise TypeError(msg)
def map_batches(
exprs: Sequence[str | Expr],
function: Callable[[Sequence[Series]], Series | Any],
return_dtype: PolarsDataType | pl.DataTypeExpr | None = None,
*,
is_elementwise: bool = False,
returns_scalar: bool = False,
) -> Expr:
"""
Map a custom function over multiple columns/expressions.
Produces a single Series result.
.. warning::
This method is much slower than the native expressions API.
Only use it if you cannot implement your logic otherwise.View on GitHub (pinned to fe841f959e)