pola-rs/polars · error

cannot set both 'index' and 'by_predicate'; mutually exclusi

Error message

cannot set both 'index' and 'by_predicate'; mutually exclusive

What it means

DataFrame.row takes mutually exclusive selectors: an integer position via `index` or a boolean expression via `by_predicate`. Passing both at once is rejected with this ValueError because the two would specify different (and possibly conflicting) rows.

Source

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

        {'foo': 3, 'bar': 8, 'ham': 'c'}

        Use `by_predicate` to return the row that matches the given predicate.

        >>> 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:

View on GitHub (pinned to df599052da)

Solutions

  1. Keep exactly one selector: use df.row(by_predicate=pl.col('id') == 42) for key-based access or df.row(0) for positional access
  2. In wrappers, resolve precedence before calling: use the predicate when provided, else the index
  3. When splatting dicts, ensure only one of 'index' / 'by_predicate' is present

Example fix

# before
row = df.row(index=0, by_predicate=pl.col('id') == 42)

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

Strategy: validation

Validate before calling

if (index is not None) == (by_predicate is not None):
    raise ValueError('pass exactly one of index / by_predicate')
row = df.row(index=index, by_predicate=by_predicate)

Prevention

When it happens

Trigger: df.row(index=0, by_predicate=pl.col('id') == 42); helper functions that accept and forward both parameters unconditionally; splatting a params dict that contains both keys.

Common situations: Generic get-row wrappers exposing both positional and predicate selection; refactors that switched a call site to by_predicate without removing index; building call arguments dynamically from user input.

Related errors


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