pandas-dev/pandas · error · TypeError

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

Error message

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

What it means

Raised by DatetimeLikeArrayMixin.astype when casting to a different datetime/timedelta dtype (e.g. datetime64 to timedelta64) or to any float dtype. These conversions are semantically invalid (datetime to float loses meaning; mixing datetime and timedelta types is undefined), so pandas rejects them outright rather than producing a silently-wrong result. Period arrays also pass through this branch.

Source

Thrown at pandas/core/arrays/datetimelike.py:461

            return super().astype(dtype, copy=copy)
        elif dtype.kind in "iu":
            # we deliberately ignore int32 vs. int64 here.
            # See https://github.com/pandas-dev/pandas/issues/24381 for more.
            values = self.asi8
            if dtype != np.int64:
                raise TypeError(
                    f"Converting from {self.dtype} to {dtype} is not supported. "
                    "Do obj.astype('int64').astype(dtype) instead"
                )

            if copy:
                values = values.copy()
            return values
        elif (dtype.kind in "mM" and self.dtype != dtype) or dtype.kind == "f":
            # disallow conversion between datetime/timedelta,
            # and conversions for any datetimelike to float
            msg = f"Cannot cast {type(self).__name__} to dtype {dtype}"
            raise TypeError(msg)
        else:
            return np.asarray(self, dtype=dtype)

    @overload  # type: ignore[override]
    def view(self) -> Self: ...

    @overload
    def view(self, dtype: Literal["M8[ns]"]) -> DatetimeArray: ...

    @overload
    def view(self, dtype: Literal["m8[ns]"]) -> TimedeltaArray: ...

    @overload
    def view(self, dtype: Dtype | None = ...) -> ArrayLike: ...

    def view(self, dtype: Dtype | None = None) -> ArrayLike:
        # we need to explicitly call super() method as long as the `@overload`s
        #  are present in this file.

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. For raw ticks, use .view('int64') then .astype(float) explicitly if you accept the semantics.
  2. For datetime<->timedelta conversion, use arithmetic (e.g. ts - epoch) instead of astype.
  3. For unit conversion, use .as_unit(...) (pandas>=2) rather than astype to another datetime dtype.

Example fix

// before
ts = pd.date_range('2020', periods=3)
ts.astype('float64')  # TypeError: Cannot cast DatetimeArray to dtype float64

// after
ts.values.astype('datetime64[ns]').view('int64').astype('float64')
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np
def to_numeric_ticks(arr):
    return arr.view('int64').astype('float64')

Type guard

import numpy as np
from typing import Any

def is_castable_dtype(arr: Any, target: Any) -> bool:
    t = np.dtype(target)
    return t.kind not in ('f',) and not (t.kind in 'mM' and t != arr.dtype)

Try / catch

try:
    arr.astype(target)
except TypeError as e:
    if 'Cannot cast' in str(e) and 'to dtype' in str(e):
        arr.view('int64').astype(target)
    else:
        raise

Prevention

When it happens

Trigger: datetime_array.astype('float64'), .astype('timedelta64[ns]') on a datetime array, .astype(np.float32) on a TimedeltaIndex, or attempting .astype('datetime64[ns]') on a timedelta array.

Common situations: Confusing timestamp and duration semantics; trying to scale nanosecond ticks via float for normalization; or generic dtype-coercion loops over mixed columns.

Related errors


AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07). Data as JSON: /api/errors/5e838e81d5cc6134. Report an issue: GitHub.