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
- Move the expression to the keyword: df.row(by_predicate=pl.col('id') == 42)
- If you meant a computed position, evaluate it first: pos = df.select(pl.col('ts').arg_max()).item(); df.row(pos)
- 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
- Apply the rule integers->index, expressions->by_predicate at every row() call site
- For computed positions, evaluate the expression first via df.select(...).item()
- Let mypy help: annotate index parameters as int | None, never IntoExpr
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
- expected `by_predicate` to be an expression, got {qualified_
- cannot select columns using key of type {qualified_type_name
- cannot select rows using key of type {qualified_type_name(ke
- cannot turn {qualified_type_name(input)!r} into selector
- Cannot pass a dictionary as a single positional argument.\nI
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/4179644e72fae243.
Report an issue: GitHub.