pola-rs/polars · error

expressions should be passed to the `by_predicate` parameter

Error message

expressions should be passed to the `by_predicate` parameter

What it means

DataFrame.row reserves `index` for integer row positions; expressions must go to the `by_predicate` parameter. Passing a pl.Expr as the positional or `index` argument — a natural mistake because many polars methods accept expressions positionally — raises this TypeError telling you to move it to by_predicate.

Source

Thrown at py-polars/src/polars/dataframe/frame.py:11866

        >>> df.row(by_predicate=(pl.col("ham") == "b"))
        (2, 7, 'b')
        """
        if index is None and by_predicate is None:
            if self.height == 1:
                index = 0
            else:
                msg = (
                    'can only call `.row()` without "index" or "by_predicate" values '
                    f"if the DataFrame has a single row; shape={self.shape!r}"
                )
                raise ValueError(msg)
        elif index is not None and by_predicate is not None:
            msg = "cannot set both 'index' and 'by_predicate'; mutually exclusive"
            raise ValueError(msg)
        elif isinstance(index, pl.Expr):
            msg = "expressions should be passed to the `by_predicate` parameter"
            raise TypeError(msg)

        if index is not None:
            row = self._df.row_tuple(index)
            if named:
                return dict(zip(self.columns, row, strict=True))
            else:
                return row

        elif by_predicate is not None:
            if not isinstance(by_predicate, pl.Expr):
                msg = f"expected `by_predicate` to be an expression, got {qualified_type_name(by_predicate)!r}"
                raise TypeError(msg)
            rows = self.filter(by_predicate).rows()
            n_rows = len(rows)
            if n_rows > 1:
                msg = f"predicate <{by_predicate!s}> returned {n_rows} rows"
                raise TooManyRowsReturnedError(msg)
            elif n_rows == 0:

View on GitHub (pinned to df599052da)

Solutions

  1. Move the expression to the keyword: df.row(by_predicate=pl.col('id') == 42)
  2. If you meant a computed position, evaluate it first: pos = df.select(pl.col('ts').arg_max()).item(); df.row(pos)
  3. Remember the rule: integers -> index, expressions -> by_predicate

Example fix

# before
row = df.row(pl.col('id') == 42)

# after
row = df.row(by_predicate=pl.col('id') == 42)
Defensive patterns

Strategy: type-guard

Validate before calling

from polars.expr import Expr

if isinstance(index, Expr):
    raise TypeError('expressions belong in by_predicate=; pass an int index')
row = df.row(index=index)

Type guard

from polars.expr import Expr

def is_row_index(v: object) -> bool:
    return v is None or (isinstance(v, int) and not isinstance(v, bool))

Prevention

When it happens

Trigger: df.row(pl.col('id') == 42); df.row(pl.first()); df.row(index=pl.col('ts').arg_max()) — any call where the first argument or index is a pl.Expr instead of an int.

Common situations: Coming from expression-style APIs (filter, select, with_columns) where expressions are passed positionally; muscle memory from Series/expr APIs; IDE autocompleting the first parameter with an expression.

Related errors


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