pandas-dev/pandas · error · ValueError

Intervals must all be closed on the same side.

Error message

Intervals must all be closed on the same side.

What it means

Raised by IntervalArray._concat_same_type (used by pd.concat / .append of IntervalArrays and IntervalIndexes) when the inputs do not all share the same 'closed' value. Intervals must be closed on a single consistent side to be concatenable.

Solutions

  1. Normalize closed first: ia2 = ia2.set_closed(ia1.closed), then concat.
  2. Align sources at construction time so they share closed.
  3. Convert to a common non-interval representation (e.g., to_tuples) if mixing closed is intentional.

Example fix

// before
pd.concat([ia1, ia2])  # closed mismatch
// after
pd.concat([ia1, ia2.set_closed(ia1.closed)])
Defensive patterns

Strategy: validation

Validate before calling

def concat_intervals(arrs):
    closed = arrs[0].closed
    if any(a.closed != closed for a in arrs):
        arrs = [a.set_closed(closed) for a in arrs]
    import pandas as pd
    return pd.concat(arrs)

Prevention

When it happens

Trigger: pd.concat([ia1, ia2]) where ia1.closed != ia2.closed; IntervalIndex.append([...]) with mismatched closed; concat of interval Series built with different closed conventions.

Common situations: Combining interval data from sources built with different defaults (from_breaks vs from_tuples); merging interval columns from separate ETL jobs.

Related errors


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

Appendix: source

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

            and self.right.equals(other.right)
        )

    @classmethod
    def _concat_same_type(cls, to_concat: Sequence[IntervalArray]) -> Self:
        """
        Concatenate multiple IntervalArray

        Parameters
        ----------
        to_concat : sequence of IntervalArray

        Returns
        -------
        IntervalArray
        """
        closed_set = {interval.closed for interval in to_concat}
        if len(closed_set) != 1:
            raise ValueError("Intervals must all be closed on the same side.")
        closed = closed_set.pop()

        left: IntervalSide = np.concatenate([interval.left for interval in to_concat])
        right: IntervalSide = np.concatenate([interval.right for interval in to_concat])

        left, right, dtype = cls._ensure_simple_new_inputs(left, right, closed=closed)

        return cls._simple_new(left, right, dtype=dtype)

    def copy(self) -> Self:
        """
        Return a copy of the array.

        Returns
        -------
        IntervalArray
        """
        left = self._left.copy()

View on GitHub (pinned to 3b7651241d)