pandas-dev/pandas · error · IndexError
index is out of bounds: must be an integer between
Error message
index is out of bounds: must be an integer between -{n} and {n - 1} What it means
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.
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.
Example fix
// before val = arr[5] # raises if len(arr) < 6 // after val = arr[5] if 0 <= 5 < len(arr) else fill_default
Defensive patterns
Strategy: validation
Validate before calling
def in_bounds(arr, i) -> bool:
n = len(arr)
return -n <= i < n Type guard
def is_in_range(arr, i) -> bool:
n = len(arr)
return -n <= i < n Try / catch
try:
arr[i]
except IndexError as e:
if "out of bounds" in str(e):
out = fill_default
else:
raise Prevention
- Bounds-check positions before indexing.
- Use Series for label-based access.
- Use take with allow_fill=True for safe access.
When it happens
Trigger: 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.
Common situations: Off-by-one loops over arr length; passing a DataFrame label that is also an integer and being mistaken for a position.
Related errors
- Cannot slice with Ellipsis
- Cannot slice with
- only integers, slices (`:`), ellipsis (`...`)…
- Only integers, slices and integer or boolean arrays are…
- only integers, slices (`:`), ellipsis (`...`)…
AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11).
Data as JSON: /api/errors/a163cd25a49a0dfa.
Report an issue: GitHub.
Appendix: source
Thrown at pandas/core/arrays/sparse/array.py:1140
if com.is_bool_indexer(key):
# mypy doesn't know we have an array here
key = cast("np.ndarray", key)
return self.take(np.arange(len(key), dtype=np.int32)[key])
elif hasattr(key, "__len__"):
return self.take(key)
else:
raise ValueError(f"Cannot slice with '{key}'")
return type(self)(data_slice, kind=self.kind)
def _get_val_at(self, loc):
n = len(self)
if loc < 0:
loc += n
if loc >= n or loc < 0:
raise IndexError(
f"index is out of bounds: must be an integer between -{n} and {n - 1}"
)
sp_loc = self.sp_index.lookup(loc)
if sp_loc == -1:
return self.fill_value
else:
val = self.sp_values[sp_loc]
val = maybe_box_datetimelike(val, self.sp_values.dtype)
return val
def take(self, indices, *, allow_fill: bool = False, fill_value=None) -> Self:
if is_scalar(indices):
raise ValueError(f"'indices' must be an array, not a scalar '{indices}'.")
indices = np.asarray(indices, dtype=np.int32)
dtype = None
if indices.size == 0:View on GitHub (pinned to 3b7651241d)