pola-rs/polars · error

index is out of bounds for DataFrame of height

Error message

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

What it means

Raised when indexing a Polars DataFrame by a single integer row position that falls outside the valid range [-height, height-1]. Polars validates the position before slicing and throws this IndexError for out-of-range row access.

Solutions

  1. Check bounds first: if 0 <= i < df.height before indexing, or handle negatives via -df.height <= i < df.height
  2. Use df.slice(i, 1) or df[i] only when the frame is known non-empty; guard empty frames explicitly
  3. If you want a labeled/conditional row lookup, use df.filter(...) instead of positional indexing

Example fix

// before
row = df[0]  # IndexError if df is empty
// after
row = df[0] if df.height > 0 else None
# or defensively:
i = 0
if -df.height <= i < df.height:
    row = df[i]
Defensive patterns

Strategy: validation

Validate before calling

i = 5
if -df.height <= i < df.height and df.height > 0:
    row = df[i]
else:
    row = None

Type guard

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

Try / catch

try:
    row = df[i]
except IndexError as e:
    if "out of bounds for DataFrame of height" in str(e):
        row = None  # or df.tail(1) as fallback
    else:
        raise

Prevention

When it happens

Trigger: df[10] on a DataFrame with fewer than 11 rows; df[-(n+1)] with a negative index beyond the first row; taking a row position computed from a filtered/differently-sized DataFrame; df.iloc-style position computed from another frame's length.

Common situations: Assuming the DataFrame has at least N rows after a filter/groupby that shrank it; off-by-one in loops over range(df.height + 1); empty DataFrame indexed as df[0].

Related errors


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

Appendix: 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 fe841f959e)