pola-rs/polars · error · NoRowsReturnedError

predicate <{by_predicate!s}> returned no rows

Error message

predicate <{by_predicate!s}> returned no rows

What it means

When DataFrame.row(by_predicate=expr) filters the frame and zero rows survive, polars raises NoRowsReturnedError (a polars.exceptions subclass) with the predicate text. This is the empty counterpart of TooManyRowsReturnedError and typically indicates the looked-up value does not exist (or the predicate never matches) rather than a programming mistake.

Source

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

        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:
                msg = f"predicate <{by_predicate!s}> returned no rows"
                raise NoRowsReturnedError(msg)

            row = rows[0]
            if named:
                return dict(zip(self.columns, row, strict=True))
            else:
                return row
        else:
            msg = "one of `index` or `by_predicate` must be set"
            raise ValueError(msg)

    @overload
    def rows(self, *, named: Literal[False] = ...) -> list[tuple[Any, ...]]: ...

    @overload
    def rows(self, *, named: Literal[True]) -> list[dict[str, Any]]: ...

    def rows(
        self, *, named: bool = False

View on GitHub (pinned to df599052da)

Solutions

  1. Verify existence first: matched = df.filter(pred); use matched only if matched.height == 1
  2. Check the comparison value's dtype and semantics (cast, strptime, dt.convert_time_zone) if matches are expected but absent
  3. For optional lookups, catch polars.exceptions.NoRowsReturnedError and return a default/fallback
  4. Handle nulls explicitly (fill_null / is_null()) since comparisons against null never match

Example fix

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

# after
matched = df.filter(pl.col('id') == 42)
row = matched.row(0) if matched.height == 1 else None
Defensive patterns

Strategy: try-catch

Validate before calling

matched = df.filter(by_predicate)
if matched.is_empty():
    row = None  # or raise your own NotFound error with context
else:
    row = matched.row(0)

Try / catch

from polars.exceptions import NoRowsReturnedError

try:
    row = df.row(by_predicate=pred)
except NoRowsReturnedError:
    row = None  # optional lookup: fall back to a default

Prevention

When it happens

Trigger: df.row(by_predicate=pl.col('id') == 42) when no row has id 42; comparing with the wrong dtype or value (string vs int, naive vs timezone-aware datetimes); predicates on an empty frame; NULL-containing keys (comparisons with null never match).

Common situations: Key lookups for ids missing from the current snapshot; date-range lookups that miss due to timezone/precision; lookup tables loaded with filters that excluded the needed rows; empty input files in pipelines.

Related errors


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