pola-rs/polars · error · TypeError

Expected Polars expression or object convertible to one, got

Error message

Expected Polars expression or object convertible to one, got {type(value)}.\n\nHint: if you tried\n    group_by(by={value!r})\nthen you probably want to use this instead:\n    group_by({value!r})

What it means

In LazyFrame.group_by(), keyword arguments define named grouping columns, so each keyword value must be a str, pl.Expr, or pl.Series. Passing another type — most commonly a dict via group_by(by={'a': 1}) or a list — raises TypeError, and the message hints at the classic mistake of wrapping the by argument in by=.

Source

Thrown at py-polars/src/polars/lazyframe/frame.py:5295

        │ a   ┆ b   ┆ c   │
        │ --- ┆ --- ┆ --- │
        │ str ┆ i64 ┆ f64 │
        ╞═════╪═════╪═════╡
        │ a   ┆ 0   ┆ 4.0 │
        │ b   ┆ 1   ┆ 3.0 │
        │ c   ┆ 1   ┆ 1.0 │
        └─────┴─────┴─────┘
        """
        for value in named_by.values():
            if not isinstance(value, (str, pl.Expr, pl.Series)):
                msg = (
                    f"Expected Polars expression or object convertible to one, got {type(value)}.\n\n"
                    "Hint: if you tried\n"
                    f"    group_by(by={value!r})\n"
                    "then you probably want to use this instead:\n"
                    f"    group_by({value!r})"
                )
                raise TypeError(msg)
        exprs = parse_into_list_of_expressions(*by, **named_by)
        lgb = self._ldf.group_by(exprs, maintain_order)
        return LazyGroupBy(lgb)

    @deprecate_renamed_parameter("by", "group_by", version="0.20.14")
    def rolling(
        self,
        index_column: IntoExpr,
        *,
        period: str | timedelta,
        offset: str | timedelta | None = None,
        closed: ClosedInterval = "right",
        group_by: IntoExpr | Iterable[IntoExpr] | None = None,
    ) -> LazyGroupBy:
        """
        Create rolling groups based on a temporal or integer column.

        Different from a `group_by_dynamic` the windows are now determined by the

View on GitHub (pinned to df599052da)

Solutions

  1. Call group_by(['a','b']) or group_by('a','b') directly without by=
  2. Use named kwargs only for renaming/aliasing with expression values: group_by(short=pl.col('long_name'))
  3. If expanding a dict programmatically, ensure values are column names, Exprs, or Series, and don't use the literal key 'by' unless its value is a column spec

Example fix

# before
lf.group_by(by=['a', 'b'])

# after
lf.group_by(['a', 'b'])
Defensive patterns

Strategy: type-guard

Validate before calling

import polars as pl
for v in named_by.values():
    assert isinstance(v, (str, pl.Expr, pl.Series)), f'invalid group_by key value: {v!r}'
lf.group_by(*by, **named_by)

Type guard

def is_valid_group_by_value(v) -> bool:
    import polars as pl
    return isinstance(v, (str, pl.Expr, pl.Series))

Prevention

When it happens

Trigger: lf.group_by(by=['a','b']) — the parameter is positional-or-keyword named by, but by= becomes a single kwarg named 'by' whose value is a list, which is not a valid named-column value; also group_by(**some_dict) where values are ints/bools.

Common situations: Copy-paste from older code or other APIs where by= keyword was standard; programmatically expanding dicts into kwargs.

Related errors


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