pandas-dev/pandas · error · TypeError

Cannot set float NaN to integer-backed IntervalArray

Error message

Cannot set float NaN to integer-backed IntervalArray

What it means

Raised by IntervalArray._validate_setitem_value when the scalar is a valid NA for the dtype but the underlying endpoint array is numpy integer-backed, which cannot store NaN. Pandas raises TypeError (not ValueError) intentionally to match the lossy-setitem contract for non-NA values on int arrays (GH#45484). Use a nullable subtype to allow NA.

Source

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

            left = right = self.left._na_value
        else:
            raise TypeError(
                "can only insert Interval objects and NA into an IntervalArray"
            )
        return left, right

    def _validate_setitem_value(self, value):
        if is_list_like(value):
            return self._validate_listlike(value)

        left, right = self._validate_scalar(value)

        if is_valid_na_for_dtype(value, self.left.dtype):
            if is_integer_dtype(self.dtype.subtype):
                # can't set NaN on a numpy integer array
                # GH#45484 TypeError, not ValueError, matches what we get with
                #  non-NA un-holdable value.
                raise TypeError("Cannot set float NaN to integer-backed IntervalArray")

        return left, right

    # ---------------------------------------------------------------------
    # Rendering Methods

    def _formatter(self, boxed: bool = False) -> Callable[[object], str]:
        # returning 'str' here causes us to render as e.g. "(0, 1]" instead of
        #  "Interval(0, 1, closed='right')"
        return str

    # ---------------------------------------------------------------------
    # Vectorized Interval Properties/Attributes

    @property
    def left(self) -> Index:
        """
        Return the left endpoints of each Interval in the IntervalArray as an Index.

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Cast the array to a nullable-integer subtype: arr = arr.astype('interval[Int64]') or 'interval[float64]' before assigning NaN.
  2. Drop the row/index rather than setting NA if the subtype must stay numpy int.
  3. Build the IntervalArray with a nullable dtype from the start via pd.array(..., dtype='interval[Int64]').

Example fix

# before
arr = pd.arrays.IntervalArray.from_tuples([(0, 1), (2, 3)])
arr[0] = np.nan

# after
arr = arr.astype('interval[float64]')
arr[0] = np.nan
Defensive patterns

Strategy: validation

Validate before calling

def can_hold_na(arr) -> bool:
    return not (np.issubdtype(arr.dtype.subtype, np.integer) and
                not isinstance(arr.dtype.subtype, pd.api.types.pandas_dtype('Int64').type))

# simpler: check the dtype string
def needs_nullable_for_na(arr):
    return 'int' in str(arr.dtype.subtype).lower() and 'Int' not in str(arr.dtype.subtype)

Type guard

def is_nullable_interval(arr) -> bool:
    sub = str(arr.dtype.subtype)
    return sub.startswith('Int') or sub.startswith('float') or sub.startswith('datetime')

Try / catch

try:
    arr[i] = np.nan
except TypeError as e:
    if 'integer-backed IntervalArray' in str(e):
        arr = arr.astype('interval[float64]')
        arr[i] = np.nan

Prevention

When it happens

Trigger: Assigning np.nan or pd.NA into an IntervalArray with dtype 'interval[int64]', e.g. arr[i] = np.nan where arr.dtype.subtype is int64.

Common situations: Migrating code that worked on float-backed intervals to int-backed intervals; cleaning data pipelines that impute NaN into interval columns; reading parquet/CSV that yielded int intervals and then trying to mask out values.

Related errors


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