pandas-dev/pandas · error · TypeError
cannot safely cast non-equivalent
Error message
cannot safely cast non-equivalent {values.dtype} to {np.dtype(dtype)} What it means
Raised by `IntegerArray._safe_cast` (NumericArray path) when lossless casting is required but impossible. It first tries numpy `astype(..., casting='safe')`; on failure it does an unsafe cast and compares element-wise — if any value changed, the cast is not equivalent and the operation is rejected. This protects integer ExtensionArrays from silently truncating floats or narrowing integers.
Solutions
- Round or floor the floats first if truncation is intended: `s.round().astype('Int64')` or `np.floor(s).astype('Int64')`.
- Use a nullable float dtype (`'Float64'`) instead of integer if fractional values are valid.
- Drop or correct the non-integer rows before casting: `s[s == s.floor()].astype('Int64')`.
- Pass `copy=False, casting='unsafe'` only via the underlying numpy array if you accept the loss; do not rely on the ExtensionArray path to do this.
Example fix
# before pd.array([1.5, 2.0, 3.0], dtype='Int64') # 1.5 is non-equivalent # after - decide semantics explicitly pd.array([1.5, 2.0, 3.0], dtype='Float64') # keep precision pd.array(np.floor([1.5, 2.0, 3.0]).astype(int), dtype='Int64') # truncate
Defensive patterns
Strategy: validation
Validate before calling
import numpy as np
def safe_to_int(s, dtype='Int64'):
s = pd.Series(s)
if np.issubdtype(s.dtype, np.floating):
if not (s.dropna() == s.dropna().floor()).all():
raise ValueError('non-integer floats present; cannot safely cast to Int')
return s.astype(dtype) Type guard
def is_lossless_int_castable(values: np.ndarray, dtype) -> bool:
try:
casted = values.astype(dtype, casting='safe')
return True
except TypeError:
casted = values.astype(dtype)
return (casted == values).all() Try / catch
try:
arr = pd.array(values, dtype='Int64')
except TypeError as e:
if 'cannot safely cast non-equivalent' in str(e):
arr = pd.array(values, dtype='Float64') # or floor first
else:
raise Prevention
- Validate `s == s.floor()` for float Series before casting to nullable Int.
- Prefer 'Float64' for any column that may legitimately hold fractions.
- After read_csv, inspect dtype and fractional-ness before coerce-to-Int.
When it happens
Trigger: Assigning a float array containing non-integer values (e.g. 1.5) into an IntegerArray/Int64 column; constructing `pd.array([1.5, 2.0], dtype='Int64')`; `astype('Int64')` on a float Series with fractional values; read_csv inferring float then coercing to nullable Int with non-integer data.
Common situations: Loading data with NaN-imputed floats into an 'Int64' column where imputation produced fractional values; merging/joining that upcasts to float64 then casting back to Int32; user passes `dtype='Int8'` to a column whose values exceed the range; arithmetic producing floats assigned back to integer nullable dtype.
Related errors
- ArrowStringArray requires a PyArrow (chunked) array of…
- Cannot cast NaN value to Integer dtype.
- cannot convert float NaN to integer
- cannot evaluate scalar only bool ops
- Expected array of type, got instead
AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11).
Data as JSON: /api/errors/cf37c4a1c9256b6b.
Report an issue: GitHub.
Appendix: 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 3b7651241d)