{"record":{"id":"b746ccea699d4d41","repo":"pola-rs/polars","slug":"index-key-is-out-of-bounds-for-dataframe-of-heig","errorCode":null,"errorMessage":"index {key} is out of bounds for DataFrame of height {num_rows}","messagePattern":"index (.+?) is out of bounds for DataFrame of height (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/_utils/getitem.py","lineNumber":299,"sourceCode":"\n\n@overload\ndef _select_rows(df: DataFrame, key: SingleIndexSelector) -> Series: ...\n\n\n@overload\ndef _select_rows(df: DataFrame, key: MultiIndexSelector) -> DataFrame: ...\n\n\ndef _select_rows(\n    df: DataFrame, key: SingleIndexSelector | MultiIndexSelector\n) -> DataFrame | Series:\n    \"\"\"Select one or more rows from the DataFrame.\"\"\"\n    if isinstance(key, int):\n        num_rows = df.height\n        if (key >= num_rows) or (key < -num_rows):\n            msg = f\"index {key} is out of bounds for DataFrame of height {num_rows}\"\n            raise IndexError(msg)\n        return df.slice(key, 1)\n\n    if isinstance(key, slice):\n        return _select_rows_by_slice(df, key)\n\n    elif isinstance(key, range):\n        key = range_to_slice(key)\n        return _select_rows_by_slice(df, key)\n\n    elif isinstance(key, Sequence):\n        if not key:\n            return df.clear()\n        if isinstance(key[0], bool):\n            _raise_on_boolean_mask()\n        s = pl.Series(\"\", key, dtype=Int64)\n        indices = _convert_series_to_indices(s, df.height)\n        return _select_rows_by_index(df, indices)\n","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/pola-rs/polars/blob/fe841f959ef4d2ceefc05a310d33ed7b1ab24e5e/py-polars/src/polars/_utils/getitem.py#L281-L317","documentation":"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.","triggerScenarios":"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.","commonSituations":"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].","solutions":["Check bounds first: if 0 <= i < df.height before indexing, or handle negatives via -df.height <= i < df.height","Use df.slice(i, 1) or df[i] only when the frame is known non-empty; guard empty frames explicitly","If you want a labeled/conditional row lookup, use df.filter(...) instead of positional indexing"],"exampleFix":"// before\nrow = df[0]  # IndexError if df is empty\n// after\nrow = df[0] if df.height > 0 else None\n# or defensively:\ni = 0\nif -df.height <= i < df.height:\n    row = df[i]","handlingStrategy":"validation","validationCode":"i = 5\nif -df.height <= i < df.height and df.height > 0:\n    row = df[i]\nelse:\n    row = None","typeGuard":"def row_in_bounds(i: int, df) -> bool:\n    return df.height > 0 and -df.height <= i < df.height","tryCatchPattern":"try:\n    row = df[i]\nexcept IndexError as e:\n    if \"out of bounds for DataFrame of height\" in str(e):\n        row = None  # or df.tail(1) as fallback\n    else:\n        raise","preventionTips":["Check df.height before positional row access, especially after filter/join","Never index an empty DataFrame; guard df.height > 0 first","Prefer df.filter(expr) or df.slice() with clamped bounds over raw indexing"],"tags":["polars","dataframe","index-out-of-bounds","row-selection"],"backgroundTag":"index-out-of-bounds","analyzedSha":"fe841f959ef4d2ceefc05a310d33ed7b1ab24e5e","analyzedAt":"2026-09-18T22:14:11.667Z","contentChangedAt":"2026-09-18T22:14:11.667Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}