pandas-dev/pandas · error · ValueError

left side of interval must be <= right side

Error message

left side of interval must be <= right side

What it means

Raised in `_validate` when for any non-missing position `left > right`. Intervals are defined with left <= right; inverted endpoints are rejected.

Solutions

  1. Swap misordered pairs: `np.minimum(left, right)`, `np.maximum(left, right)` if direction is irrelevant.
  2. Fix the upstream computation so right >= left (e.g. add bin width, do not subtract).
  3. Drop or flag rows where left > right if they are genuinely invalid data.

Example fix

# before
IntervalArray.from_arrays([5,1],[1,2])

# after - canonicalise order
import numpy as np
l = np.array([5,1]); r = np.array([1,2])
IntervalArray.from_arrays(np.minimum(l,r), np.maximum(l,r))
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np

def ensure_left_le_right(left, right):
    left = np.asarray(left)
    right = np.asarray(right)
    if (left[~np.isnan(left)] > right[~np.isnan(right)]).any():
        raise ValueError('found left > right')
    return left, right

Type guard

import numpy as np

def left_le_right(left, right) -> bool:
    left, right = np.asarray(left), np.asarray(right)
    mask = ~(np.isnan(left) | np.isnan(right))
    return (left[mask] <= right[mask]).all()

Try / catch

try:
    arr = IntervalArray.from_arrays(left, right)
except ValueError as e:
    if 'left side of interval must be' in str(e):
        l, r = np.minimum(left, right), np.maximum(left, right)
        arr = IntervalArray.from_arrays(l, r)
    else:
        raise

Prevention

When it happens

Trigger: `IntervalArray.from_arrays([5,1],[1,2])` (5 > 1 at position 0); bounds swapped during data prep; right bound computed as left minus something.

Common situations: Off-by-one in bin computation; swapped column order in the source; negative durations produced by subtraction bugs.

Related errors


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

Appendix: source

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

        * left is always below right
        """
        if not isinstance(dtype, IntervalDtype):
            msg = f"invalid dtype: {dtype}"
            raise ValueError(msg)
        if len(left) != len(right):
            msg = "left and right must have the same length"
            raise ValueError(msg)
        left_mask = notna(left)
        right_mask = notna(right)
        if not (left_mask == right_mask).all():
            msg = (
                "missing values must be missing in the same "
                "location both left and right sides"
            )
            raise ValueError(msg)
        if not (left[left_mask] <= right[left_mask]).all():
            msg = "left side of interval must be <= right side"
            raise ValueError(msg)

    def _shallow_copy(self, left, right) -> Self:
        """
        Return a new IntervalArray with the replacement attributes

        Parameters
        ----------
        left : Index
            Values to be used for the left-side of the intervals.
        right : Index
            Values to be used for the right-side of the intervals.
        """
        dtype = IntervalDtype(left.dtype, closed=self.closed)
        left, right, dtype = self._ensure_simple_new_inputs(left, right, dtype=dtype)

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

    # ---------------------------------------------------------------------

View on GitHub (pinned to 3b7651241d)