pola-rs/polars · error · IndexError

index {key} is out of bounds for DataFrame of height {num_ro

Error message

index {key} is out of bounds for DataFrame of height {num_rows}

What it means

_select_rows (getitem.py:299) bounds-checks integer row keys before slicing: a single-int key must satisfy -df.height <= key < df.height (checked as key >= num_rows or key < -num_rows). Out-of-range indices raise this IndexError because the row is fetched with df.slice(key, 1), which cannot silently return nothing.

Source

Thrown at py-polars/src/polars/_utils/getitem.py:299


@overload
def _select_rows(df: DataFrame, key: SingleIndexSelector) -> Series: ...


@overload
def _select_rows(df: DataFrame, key: MultiIndexSelector) -> DataFrame: ...


def _select_rows(
    df: DataFrame, key: SingleIndexSelector | MultiIndexSelector
) -> DataFrame | Series:
    """Select one or more rows from the DataFrame."""
    if isinstance(key, int):
        num_rows = df.height
        if (key >= num_rows) or (key < -num_rows):
            msg = f"index {key} is out of bounds for DataFrame of height {num_rows}"
            raise IndexError(msg)
        return df.slice(key, 1)

    if isinstance(key, slice):
        return _select_rows_by_slice(df, key)

    elif isinstance(key, range):
        key = range_to_slice(key)
        return _select_rows_by_slice(df, key)

    elif isinstance(key, Sequence):
        if not key:
            return df.clear()
        if isinstance(key[0], bool):
            _raise_on_boolean_mask()
        s = pl.Series("", key, dtype=Int64)
        indices = _convert_series_to_indices(s, df.height)
        return _select_rows_by_index(df, indices)

View on GitHub (pinned to df599052da)

Solutions

  1. Bounds-check before access: 0 <= i < df.height or -df.height <= i < 0
  2. Use df.slice(i, n), df.head(n), or df.tail(n) which clamp instead of raising
  3. Recompute positions after transformations, or key rows with df.with_row_index('i') and filter on it

Example fix

# before
row = df[i]            # IndexError after filtering shrank df

# after
row = df[i] if -df.height <= i < df.height else None
Defensive patterns

Strategy: validation

Validate before calling

i = int(i)
if not (-df.height <= i < df.height):
    raise IndexError(f"row {i} out of range for height {df.height}")
row = df[i]

Type guard

def in_row_bounds(df, i: int) -> bool:
    return -df.height <= i < df.height

Try / catch

try:
    row = df[i]
except IndexError:
    row = None  # or log and skip

Prevention

When it happens

Trigger: df[10] on a 3-row frame; df[-7] on a 3-row frame; df[0] or df[i, 'a'] on a frame left empty after a filter/collect; i taken from range(len(bigger_df)).

Common situations: Off-by-one after head()/filter()/join() shrank the frame; indices captured before a transformation and reused after; iterating with a stale length after dropping rows.

Related errors


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