pandas-dev/pandas · error · ValueError

Cannot slice with Ellipsis

Error message

Cannot slice with Ellipsis

What it means

Raised by SparseArray.__getitem__ when a tuple key unpacks to Ellipsis. SparseArray's __getitem__ supports integer, slice, and list-like keys but does not implement ndarray-style Ellipsis expansion, so a leftover Ellipsis is treated as an invalid slice.

Solutions

  1. Remove the Ellipsis; index directly as arr[0] or arr[:].
  2. Normalize keys before indexing: drop Ellipsis for 1-D sparse arrays.
  3. Materialize to dense with np.asarray(arr)[key] if Ellipsis semantics are required.

Example fix

// before
arr[..., 0]  # raises
// after
arr[0]
Defensive patterns

Strategy: validation

Validate before calling

def strip_ellipsis_key(key):
    import numpy as np
    if isinstance(key, tuple):
        key = tuple(k for k in key if k is not ...)
        return key[0] if len(key) == 1 else key
    return key

Type guard

def key_has_ellipsis(key) -> bool:
    return key is ... or (isinstance(key, tuple) and ... in key)

Try / catch

try:
    arr[key]
except ValueError as e:
    if "Cannot slice with Ellipsis" in str(e):
        key = strip_ellipsis_key(key)
        out = arr[key]
    else:
        raise

Prevention

When it happens

Trigger: Indexing arr[..., 0], arr[Ellipsis], or passing a tuple containing Ellipsis that unpack_tuple_and_ellipses cannot fully eliminate for a 1-D sparse array.

Common situations: Generic N-D indexing code reused against a 1-D SparseArray; numpy-style ellipsis indexing ported from dense arrays.

Related errors


AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11). Data as JSON: /api/errors/6327581ce48d01cb. Report an issue: GitHub.

Appendix: source

Thrown at pandas/core/arrays/sparse/array.py:1049

            index = Index(keys, copy=False)
        else:
            index = keys
        return Series(counts, index=index, copy=False)

    # --------
    # Indexing
    # --------
    @overload
    def __getitem__(self, key: ScalarIndexer) -> Any: ...

    @overload
    def __getitem__(self, key: SequenceIndexer) -> Self: ...

    def __getitem__(self, key: PositionalIndexer) -> Self | Any:
        if isinstance(key, tuple):
            key = unpack_tuple_and_ellipses(key)
            if key is ...:
                raise ValueError("Cannot slice with Ellipsis")

        if is_integer(key):
            return self._get_val_at(key)
        elif isinstance(key, tuple):
            data_slice = self.to_dense()[key]
        elif isinstance(key, slice):
            if key == slice(None):
                # to ensure arr[:] (used by view()) does not make a copy
                result = type(self)._simple_new(
                    self.sp_values, self.sp_index, self.dtype
                )
                result._readonly = self._readonly
                return result
            # Avoid densifying when handling contiguous slices
            if key.step is None or key.step == 1:
                start = 0 if key.start is None else key.start
                if start < 0:
                    start += len(self)

View on GitHub (pinned to 3b7651241d)