{"record":{"id":"c820fff89dadb54c","repo":"pandas-dev/pandas","slug":"left-side-of-interval-must-be-right-side","errorCode":null,"errorMessage":"left side of interval must be <= right side","messagePattern":"left side of interval must be <= right side","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/interval.py","lineNumber":623,"sourceCode":"        * left is always below right\n        \"\"\"\n        if not isinstance(dtype, IntervalDtype):\n            msg = f\"invalid dtype: {dtype}\"\n            raise ValueError(msg)\n        if len(left) != len(right):\n            msg = \"left and right must have the same length\"\n            raise ValueError(msg)\n        left_mask = notna(left)\n        right_mask = notna(right)\n        if not (left_mask == right_mask).all():\n            msg = (\n                \"missing values must be missing in the same \"\n                \"location both left and right sides\"\n            )\n            raise ValueError(msg)\n        if not (left[left_mask] <= right[left_mask]).all():\n            msg = \"left side of interval must be <= right side\"\n            raise ValueError(msg)\n\n    def _shallow_copy(self, left, right) -> Self:\n        \"\"\"\n        Return a new IntervalArray with the replacement attributes\n\n        Parameters\n        ----------\n        left : Index\n            Values to be used for the left-side of the intervals.\n        right : Index\n            Values to be used for the right-side of the intervals.\n        \"\"\"\n        dtype = IntervalDtype(left.dtype, closed=self.closed)\n        left, right, dtype = self._ensure_simple_new_inputs(left, right, dtype=dtype)\n\n        return self._simple_new(left, right, dtype=dtype)\n\n    # ---------------------------------------------------------------------","sourceCodeStart":605,"sourceCodeEnd":641,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/arrays/interval.py#L605-L641","documentation":"Raised by `_validate` when any element has `left > right`. By definition an interval's lower bound must not exceed its upper bound (equality is allowed). Fires at pandas/core/arrays/interval.py:623.","triggerScenarios":"`from_arrays([2, 1], [1, 2])`, swapped columns, or bounds computed from min/max where the source data is dirty.","commonSituations":"Column order accidentally swapped in a pipeline; high/low labels inverted; timezone or unit conversions that reverse ordering.","solutions":["Swap misordered bounds: `lo, hi = np.minimum(left, right), np.maximum(left, right)`.","Drop invalid rows: `valid = left <= right; left, right = left[valid], right[valid]`.","Verify column mapping in the source query/ETL."],"exampleFix":"// before\npd.IntervalIndex.from_arrays(df['hi'], df['lo'])  # swapped\n// after\nimport numpy as np\nlo = np.minimum(df['hi'], df['lo'])\nhi = np.maximum(df['hi'], df['lo'])\npd.IntervalIndex.from_arrays(lo, hi)","handlingStrategy":"validation","validationCode":"import numpy as np\n\ndef enforce_order(left, right):\n    left = np.asarray(left)\n    right = np.asarray(right)\n    lo = np.minimum(left, right)\n    hi = np.maximum(left, right)\n    return lo, hi","typeGuard":"import numpy as np\n\ndef all_left_leq_right(left, right) -> bool:\n    mask = ~(np.isnan(left) | np.isnan(right))\n    return bool((left[mask] <= right[mask]).all())","tryCatchPattern":"try:\n    ia = pd.IntervalArray(left, right)\nexcept ValueError as e:\n    if \"left side of interval must be <= right side\" in str(e):\n        lo, hi = np.minimum(left, right), np.maximum(left, right)\n        ia = pd.IntervalArray(lo, hi)\n    else:\n        raise","preventionTips":["Sort columns so low always precedes high at ingestion.","Use np.minimum/maximum to auto-swap if direction is uncertain.","Drop or quarantine rows where left > right after domain validation."],"tags":["interval","bounds","validation","ordering"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}