pandas-dev/pandas · error · TypeError

cannot safely cast non-equivalent {values.dtype} to {np.dtyp

Error message

cannot safely cast non-equivalent {values.dtype} to {np.dtype(dtype)}

What it means

Raised by IntegerArray._safe_cast when converting values to an integer dtype cannot be done losslessly (e.g. floats with fractional parts cast to int). 'safe' numpy casting failed and a follow-up equality check found data loss, so pandas refuses rather than silently truncate. TypeError naming both dtypes.

Source

Thrown at pandas/core/arrays/integer.py:69

    def _get_dtype_mapping(cls) -> dict[np.dtype, IntegerDtype]:
        return NUMPY_INT_TO_DTYPE

    @classmethod
    def _safe_cast(cls, values: np.ndarray, dtype: np.dtype, copy: bool) -> np.ndarray:
        """
        Safely cast the values to the given dtype.

        "safe" in this context means the casting is lossless. e.g. if 'values'
        has a floating dtype, each value must be an integer.
        """
        try:
            return values.astype(dtype, casting="safe", copy=copy)
        except TypeError as err:
            casted = values.astype(dtype, copy=copy)
            if (casted == values).all():
                return casted

            raise TypeError(
                f"cannot safely cast non-equivalent {values.dtype} to {np.dtype(dtype)}"
            ) from err


@set_module("pandas.arrays")
class IntegerArray(NumericArray):
    """
    Array of integer (optional missing) values.

    Uses :attr:`pandas.NA` as the missing value.

    .. warning::

       IntegerArray is currently experimental, and its API or internal
       implementation may change without warning.

    We represent an IntegerArray with 2 numpy arrays:

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Round or floor first if truncation is intended: s.round().astype('Int64').
  2. Use a nullable float dtype ('Float64') if fractional values are legitimate.
  3. Clean the data so every value is integral before casting.

Example fix

# before
pd.Series([1.5, 2.0]).astype('Int64')
# after
pd.Series([1.5, 2.0]).round().astype('Int64')
Defensive patterns

Strategy: validation

Validate before calling

def to_int_nullable(s):
    if pd.api.types.is_float_dtype(s) and not (s.dropna() % 1 == 0).all():
        raise TypeError('float values are not integral; round or use Float64')
    return s.astype('Int64')

Type guard

def is_integral_float(s) -> bool:
    return pd.api.types.is_float_dtype(s) and bool((s.dropna() % 1 == 0).all())

Prevention

When it happens

Trigger: Constructing a nullable IntegerArray ('Int64') from float data with non-integer values; astype('Int64') on a Series like [1.5, 2.0]; providing floats to a constructor expecting integer extension dtype.

Common situations: CSV/JSON parsed as float then cast to Int64 without rounding; mixing units where some rows are fractional; assuming integer-valued floats round-trip to Int64.

Related errors


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