pandas-dev/pandas · error · TypeError

Cannot cast to dtype

Error message

Cannot cast {type(self).__name__} to dtype {dtype}

What it means

Raised in IntervalArray.astype's else-branch: the target dtype is not an IntervalDtype and the parent ExtensionArray.astype raised TypeError or ValueError. IntervalArrays cannot be cast directly to plain numeric, string, or object dtypes because the interval structure has no such representation.

Solutions

  1. Cast endpoints separately: arr.left.astype(...) or arr.right.astype(...).
  2. Use arr.to_tuples() for an object/tuple representation.
  3. Materialize as object ndarray via np.asarray(arr) when you really need Interval objects.

Example fix

// before
arr.astype('int64')
// after
arr.left.astype('int64')
Defensive patterns

Strategy: type-guard

Validate before calling

from pandas import IntervalDtype
from pandas.api.types import pandas_dtype

def cast_interval_endpoints(arr, target):
    return arr.left.astype(target), arr.right.astype(target)

Type guard

from pandas import IntervalDtype
from pandas.api.types import pandas_dtype

def is_interval_dtype_target(target):
    return isinstance(pandas_dtype(target), IntervalDtype)

Prevention

When it happens

Trigger: arr.astype('int64'); arr.astype('float64'); arr.astype(str); arr.astype(object) directly on an IntervalArray.

Common situations: Trying to extract endpoint numerics by casting the whole array; misunderstanding that endpoints live on .left/.right.

Related errors


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

Appendix: source

Thrown at pandas/core/arrays/interval.py:971

                new_left = Index(self._left, copy=False).astype(dtype.subtype)
                new_right = Index(self._right, copy=False).astype(dtype.subtype)
            except IntCastingNaNError:
                # e.g test_subtype_integer
                raise
            except (TypeError, ValueError) as err:
                # e.g. test_subtype_integer_errors f8->u8 can be lossy
                #  and raises ValueError
                msg = (
                    f"Cannot convert {self.dtype} to {dtype}; subtypes are incompatible"
                )
                raise TypeError(msg) from err
            return self._shallow_copy(new_left, new_right)
        else:
            try:
                return super().astype(dtype, copy=copy)
            except (TypeError, ValueError) as err:
                msg = f"Cannot cast {type(self).__name__} to dtype {dtype}"
                raise TypeError(msg) from err

    def equals(self, other) -> bool:
        if type(self) != type(other):
            return False

        return bool(
            self.closed == other.closed
            and self.left.equals(other.left)
            and self.right.equals(other.right)
        )

    @classmethod
    def _concat_same_type(cls, to_concat: Sequence[IntervalArray]) -> Self:
        """
        Concatenate multiple IntervalArray

        Parameters
        ----------

View on GitHub (pinned to 3b7651241d)