{"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":"validation","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/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/arrays/interval.py#L605-L641","documentation":"Raised in `_validate` when for any non-missing position `left > right`. Intervals are defined with left <= right; inverted endpoints are rejected.","triggerScenarios":"`IntervalArray.from_arrays([5,1],[1,2])` (5 > 1 at position 0); bounds swapped during data prep; right bound computed as left minus something.","commonSituations":"Off-by-one in bin computation; swapped column order in the source; negative durations produced by subtraction bugs.","solutions":["Swap misordered pairs: `np.minimum(left, right)`, `np.maximum(left, right)` if direction is irrelevant.","Fix the upstream computation so right >= left (e.g. add bin width, do not subtract).","Drop or flag rows where left > right if they are genuinely invalid data."],"exampleFix":"# before\nIntervalArray.from_arrays([5,1],[1,2])\n\n# after - canonicalise order\nimport numpy as np\nl = np.array([5,1]); r = np.array([1,2])\nIntervalArray.from_arrays(np.minimum(l,r), np.maximum(l,r))","handlingStrategy":"validation","validationCode":"import numpy as np\n\ndef ensure_left_le_right(left, right):\n    left = np.asarray(left)\n    right = np.asarray(right)\n    if (left[~np.isnan(left)] > right[~np.isnan(right)]).any():\n        raise ValueError('found left > right')\n    return left, right","typeGuard":"import numpy as np\n\ndef left_le_right(left, right) -> bool:\n    left, right = np.asarray(left), np.asarray(right)\n    mask = ~(np.isnan(left) | np.isnan(right))\n    return (left[mask] <= right[mask]).all()","tryCatchPattern":"try:\n    arr = IntervalArray.from_arrays(left, right)\nexcept ValueError as e:\n    if 'left side of interval must be' in str(e):\n        l, r = np.minimum(left, right), np.maximum(left, right)\n        arr = IntervalArray.from_arrays(l, r)\n    else:\n        raise","preventionTips":["Verify left <= right element-wise before from_arrays.","If direction is irrelevant, canonicalise with min/max.","Inspect any row where left > right as a likely data bug."],"tags":["interval","endpoint-order","value-error"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}