pandas-dev/pandas · error · TypeError

Cannot cast to dtype

Error message

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

What it means

Raised in DatetimeLikeArray.astype when converting a datetimelike array to a float dtype, or when converting between datetime and timedelta kinds (e.g., datetime64 to timedelta64). Floats cannot represent datetimelike ticks without losing the unit semantics, and cross-kind conversions (datetime<->timedelta) are nonsensical, so both are rejected.

Solutions

  1. For epoch values: dti.view('int64') or (dti - epoch) // pd.Timedelta('1s') for seconds.
  2. For timedelta as numeric seconds: tdi.total_seconds() (on TimedeltaIndex) or tdi.view('int64') / 1e9.
  3. To reinterpret datetime64 bits as timedelta64 (rare): use .view('timedelta64[ns]') not .astype.
  4. Keep datetimelike data in its native dtype; convert to int64 first if a numeric form is truly needed.

Example fix

# before
dti.astype('float64')  # TypeError

# after
(dti.view('int64') / 1e9)  # epoch seconds as float
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np
if dtype.kind in 'fc' or (dtype.kind in 'mM' and dti.dtype != dtype):
    raise TypeError(f'Cannot cast {dti.dtype} to {dtype}; use .view or numeric conversion')
dti.astype(dtype)

Type guard

def castable_from_datetimelike(src_dtype, target_dtype) -> bool:
    import numpy as np
    if target_dtype.kind == 'f':
        return False
    if target_dtype.kind in 'mM' and src_dtype != target_dtype:
        return False
    return True

Try / catch

try:
    dti.astype('float64')
except TypeError as e:
    if 'Cannot cast' in str(e):
        dti.view('int64') / 1e9
    else:
        raise

Prevention

When it happens

Trigger: dti.astype('float64'), tdi.astype(np.float32'), dti.astype('timedelta64[ns]'), tdi.astype('datetime64[ns]'). Period values cast to float. Converting a datetime column to float for legacy serialization.

Common situations: User expects astype('float') to yield epoch seconds — it does not; use .view or division by the unit. Cross-kind cast after a wrong df.astype({...}) mapping. Migration code that previously used .values.astype(float).

Related errors


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

Appendix: 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 3b7651241d)