{"record":{"id":"a163cd25a49a0dfa","repo":"pandas-dev/pandas","slug":"index-is-out-of-bounds-must-be-an-integer-between","errorCode":null,"errorMessage":"index is out of bounds: must be an integer between -{n} and {n - 1}","messagePattern":"index is out of bounds: must be an integer between -(.+?) and (.+?)","errorType":"exception","errorClass":"IndexError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/sparse/array.py","lineNumber":1135,"sourceCode":"\n            if com.is_bool_indexer(key):\n                # mypy doesn't know we have an array here\n                key = cast(\"np.ndarray\", key)\n                return self.take(np.arange(len(key), dtype=np.int32)[key])\n            elif hasattr(key, \"__len__\"):\n                return self.take(key)\n            else:\n                raise ValueError(f\"Cannot slice with '{key}'\")\n\n        return type(self)(data_slice, kind=self.kind)\n\n    def _get_val_at(self, loc):\n        n = len(self)\n        if loc < 0:\n            loc += n\n\n        if loc >= n or loc < 0:\n            raise IndexError(\n                f\"index is out of bounds: must be an integer between -{n} and {n - 1}\"\n            )\n\n        sp_loc = self.sp_index.lookup(loc)\n        if sp_loc == -1:\n            return self.fill_value\n        else:\n            val = self.sp_values[sp_loc]\n            val = maybe_box_datetimelike(val, self.sp_values.dtype)\n            return val\n\n    def take(self, indices, *, allow_fill: bool = False, fill_value=None) -> Self:\n        if is_scalar(indices):\n            raise ValueError(f\"'indices' must be an array, not a scalar '{indices}'.\")\n        indices = np.asarray(indices, dtype=np.int32)\n\n        dtype = None\n        if indices.size == 0:","sourceCodeStart":1117,"sourceCodeEnd":1153,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/arrays/sparse/array.py#L1117-L1153","documentation":"Raised by SparseArray._get_val_at when the requested integer position loc is outside [-n, n-1] after negative-index normalization. It mirrors numpy IndexError semantics but is emitted from the sparse lookup path so the caller learns the valid bounds before the sp_index is consulted. Negative indices are folded by adding len(self) once; anything still negative or >= n is rejected.","triggerScenarios":"Calling _get_val_at(loc) with loc >= len(sparse_arr) or loc < -len(sparse_arr), often indirectly via argmax/argmin internals, repr formatting of a stale cached index, or user code computing positions from a different-length array.","commonSituations":"Off-by-one loops, using .idxmax() results from one Series to index another of different length, caching a length then appending/trimming the array, or negative indexing math that overshoots (e.g. loc=-n-1).","solutions":["Clamp/normalize the index before lookup: loc = loc if loc >= 0 else loc + len(arr); assert 0 <= loc < len(arr).","Use sparse_arr.iloc[loc] semantics via a Series wrapper which standardizes bounds handling.","Recompute the length at call time instead of reusing a cached n."],"exampleFix":"// before\nn = len(arr)\nval = arr._get_val_at(user_pos)  # user_pos may exceed n\n\n// after\nloc = user_pos % len(arr)  # or an explicit bounds check\nval = arr._get_val_at(loc)","handlingStrategy":"validation","validationCode":"def safe_get_val_at(arr, loc):\n    n = len(arr)\n    loc = loc + n if loc < 0 else loc\n    if not (0 <= loc < n):\n        raise IndexError(f'loc {loc} out of range for length {n}')\n    return arr._get_val_at(loc)","typeGuard":"def is_in_bounds(arr, loc) -> bool:\n    n = len(arr)\n    return -n <= loc < n","tryCatchPattern":"try:\n    val = arr._get_val_at(loc)\nexcept IndexError as e:\n    if 'out of bounds' in str(e):\n        # handle missing position\n        val = arr.fill_value\n    else:\n        raise","preventionTips":["Recompute len(arr) at call time rather than caching","Normalize negative indices with loc %= len(arr) only when wrapping is intended","Use Series.iloc for bounds-safe positional access"],"tags":["sparse","indexing","bounds","out-of-bounds"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}