{"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":1140,"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":1122,"sourceCodeEnd":1158,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/arrays/sparse/array.py#L1122-L1158","documentation":"IndexError from SparseArray._get_val_at when a positional location resolves outside [-n, n-1]. Locations are normalized for negatives, then checked against the array length before sparse-index lookup.","triggerScenarios":"arr[5] on a length-3 SparseArray; arr[-10] on a length-3 array; an integer key that is a valid Python int but out of range.","commonSituations":"Off-by-one loops over arr length; passing a DataFrame label that is also an integer and being mistaken for a position.","solutions":["Bounds-check before access: if -n <= i < n: ... else handle.","Use pd.Series(arr, index=labels)[label] for label-based access.","Use arr.take([i], allow_fill=True) to get fill_value instead of an IndexError for -1 sentinel."],"exampleFix":"// before\nval = arr[5]  # raises if len(arr) < 6\n// after\nval = arr[5] if 0 <= 5 < len(arr) else fill_default","handlingStrategy":"validation","validationCode":"def in_bounds(arr, i) -> bool:\n    n = len(arr)\n    return -n <= i < n","typeGuard":"def is_in_range(arr, i) -> bool:\n    n = len(arr)\n    return -n <= i < n","tryCatchPattern":"try:\n    arr[i]\nexcept IndexError as e:\n    if \"out of bounds\" in str(e):\n        out = fill_default\n    else:\n        raise","preventionTips":["Bounds-check positions before indexing.","Use Series for label-based access.","Use take with allow_fill=True for safe access."],"tags":["sparse","indexing","out-of-bounds","getitem"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}