pandas-dev/pandas · error · ValueError

missing values must be missing in the same location both…

Error message

missing values must be missing in the same location both left and right sides

What it means

Raised in `_validate` when the NA masks of left and right differ — `(left_mask == right_mask).all()` fails. Intervals must be missing on both sides at the same positions; a half-missing interval is not representable.

Solutions

  1. Make NA positions symmetric: `mask = left.isna() | right.isna()` then `left[mask] = right[mask] = NA`.
  2. Drop rows where either side is NA before constructing.
  3. Investigate upstream: a single-sided NaN usually indicates a data bug.

Example fix

# before
left = pd.Series([0, np.nan, 2]); right = pd.Series([1, 5, 3])
IntervalArray.from_arrays(left, right)

# after - symmetric mask
mask = left.isna() | right.isna()
left, right = left.mask(mask, np.nan), right.mask(mask, np.nan)
IntervalArray.from_arrays(left, right)
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np
import pandas as pd

def symmetrise_na(left, right):
    left, right = pd.Series(left), pd.Series(right)
    mask = left.isna() | right.isna()
    return left.mask(mask, np.nan), right.mask(mask, np.nan)

Type guard

import pandas as pd

def na_masks_match(left, right) -> bool:
    return (pd.isna(left) == pd.isna(right)).all()

Try / catch

try:
    arr = IntervalArray.from_arrays(left, right)
except ValueError as e:
    if 'missing in the same location' in str(e):
        l, r = symmetrise_na(left, right)
        arr = IntervalArray.from_arrays(l, r)
    else:
        raise

Prevention

When it happens

Trigger: left has NaN at index 2 but right has a value there; imputing only one side; joining bounds where one side has more NaNs.

Common situations: Data cleaning that fills NaN on the upper bound but not lower; arithmetic producing NaN on one side only (e.g. left shifted); merging series with different missingness.

Related errors


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

Appendix: source

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

        * dtype is correct
        * left and right match lengths
        * left and right have the same missing values
        * 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)

View on GitHub (pinned to 3b7651241d)