pandas-dev/pandas · error · TypeError

can only insert Interval objects and NA into an IntervalArra

Error message

can only insert Interval objects and NA into an IntervalArray

What it means

Raised by IntervalArray._validate_scalar when a scalar value passed to insert/fill/shift is neither a pd.Interval nor a recognised NA (is_valid_na_for_dtype returns False). IntervalArray only accepts Interval objects or NA as scalar payloads. The guard is reached by insert(), _validate_setitem_value scalar path, and shift(fill_value=...).

Source

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

            msg = (
                "'value' should be a compatible interval type, "
                f"got {type(value)} instead."
            )
            raise TypeError(msg) from err

        return value_left, value_right

    def _validate_scalar(self, value):
        if isinstance(value, Interval):
            self._check_closed_matches(value, name="value")
            left, right = value.left, value.right
            self.left._validate_fill_value(left)
            self.left._validate_fill_value(right)
        elif is_valid_na_for_dtype(value, self.left.dtype):
            # GH#18295
            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

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Pass a pd.Interval(left, right, closed=arr.closed) as the scalar to insert().
  2. Pass pd.NA (or np.nan for float-backed) when the intent is a missing value.
  3. If you need a numeric value, switch to the underlying endpoints via arr.left / arr.right rather than the interval array.

Example fix

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

# after
arr.insert(1, pd.Interval(5, 6, closed=arr.closed))
Defensive patterns

Strategy: type-guard

Validate before calling

def interval_or_na(value, closed):
    if value is pd.NA or value is None or (isinstance(value, float) and np.isnan(value)):
        return pd.NA
    if isinstance(value, pd.Interval):
        if value.closed != closed:
            raise ValueError('closed mismatch')
        return value
    raise TypeError('pass an Interval or pd.NA')

Type guard

def is_interval_or_na(value) -> bool:
    return isinstance(value, pd.Interval) or value is pd.NA or value is None

Prevention

When it happens

Trigger: Calling arr.insert(loc, 5) on an IntervalArray, arr.fillna(0), or shift(fill_value=-1) where the fill is a plain scalar rather than an Interval or NA.

Common situations: Treating an IntervalArray like a numeric array and trying to insert a single number, or assuming 0 / '' is a safe fill.

Related errors


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