pandas-dev/pandas · error · ValueError

{name}.from_tuples requires tuples of length 2, got {d}

Error message

{name}.from_tuples requires tuples of length 2, got {d}

What it means

Raised by `IntervalArray.from_tuples` / `IntervalIndex.from_tuples` when unpacking an entry as `lhs, rhs = d` fails with a ValueError because the tuple has a length other than 2 (e.g., a 3-tuple or 1-tuple). Each input must be exactly a pair. Fires at pandas/core/arrays/interval.py:586.

Source

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

        Length: 2, dtype: interval[int64, right]
        """
        if len(data):
            left, right = [], []
        else:
            # ensure that empty data keeps input dtype
            left = right = data

        for d in data:
            if not isinstance(d, tuple) and isna(d):
                lhs = rhs = np.nan
            else:
                name = cls.__name__
                try:
                    # need list of length 2 tuples, e.g. [(0, 1), (1, 2), ...]
                    lhs, rhs = d
                except ValueError as err:
                    msg = f"{name}.from_tuples requires tuples of length 2, got {d}"
                    raise ValueError(msg) from err
                except TypeError as err:
                    msg = f"{name}.from_tuples received an invalid item, {d}"
                    raise TypeError(msg) from err
            left.append(lhs)
            right.append(rhs)

        return cls.from_arrays(left, right, closed, copy=False, dtype=dtype)

    @classmethod
    def _validate(cls, left, right, dtype: IntervalDtype) -> None:
        """
        Verify that the IntervalArray is valid.

        Checks that

        * dtype is correct
        * left and right match lengths
        * left and right have the same missing values

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Project to exactly two columns: `df[['low','high']].itertuples(index=False, name=None)`.
  2. Filter/repair malformed tuples before calling: `[t for t in data if isinstance(t, tuple) and len(t) == 2]`.
  3. Use `from_arrays(left, right)` instead when bounds already live in two sequences.

Example fix

// before
pd.IntervalIndex.from_tuples(df[['lo','mid','hi']].itertuples(index=False, name=None))
// after
pd.IntervalIndex.from_tuples(df[['lo','hi']].itertuples(index=False, name=None))
Defensive patterns

Strategy: validation

Validate before calling

def clean_tuples(data):
    out = []
    for d in data:
        if isinstance(d, tuple) and len(d) == 2:
            out.append(d)
        elif isinstance(d, tuple):
            raise ValueError(f"tuple of length {len(d)} is not 2: {d!r}")
    return out

Type guard

def all_pairs(data) -> bool:
    return all(isinstance(d, tuple) and len(d) == 2 for d in data)

Try / catch

try:
    ii = pd.IntervalIndex.from_tuples(data)
except ValueError as e:
    if "requires tuples of length 2" in str(e):
        ii = pd.IntervalIndex.from_tuples([t for t in data if isinstance(t, tuple) and len(t) == 2])
    else:
        raise

Prevention

When it happens

Trigger: `pd.IntervalIndex.from_tuples([(0,1,2), (3,4)])`, or rows from a DataFrame with 3+ columns: `from_tuples(df[['a','b','c']].itertuples(...))`.

Common situations: Passing `zip(a, b, c)` by accident, or itertuples including the index as the first element.

Related errors


AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07). Data as JSON: /api/errors/ed443e76c869fa56. Report an issue: GitHub.