pandas-dev/pandas · error · ValueError

.from_tuples requires tuples of length 2, got

Error message

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

What it means

Raised inside `_from_sequence_of_custom` / the from_tuples path when iterating `data` and unpacking `lhs, rhs = d` raises a ValueError — i.e. the tuple does not have exactly 2 elements. Each item must be a length-2 tuple (or NA).

Solutions

  1. Sanitise the tuples to length 2 before passing: `[t[:2] for t in data]`.
  2. If you have left/right/mid, pick the two you want explicitly and use `from_arrays`.
  3. Validate `all(len(t) == 2 for t in data)` before calling from_tuples.

Example fix

# before
pd.arrays.IntervalArray.from_tuples([(0,1,2), (3,4,5)])

# after
pd.arrays.IntervalArray.from_tuples([(0,1), (3,4)])
# or slice to first two
pd.arrays.IntervalArray.from_tuples([t[:2] for t in [(0,1,2),(3,4,5)]])
Defensive patterns

Strategy: validation

Validate before calling

def clean_tuples(data):
    out = []
    for t in data:
        if isinstance(t, tuple) and len(t) == 2:
            out.append(t)
        else:
            out.append((pd.NA, pd.NA))
    return out

Type guard

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

Try / catch

try:
    arr = pd.arrays.IntervalArray.from_tuples(data)
except ValueError as e:
    if 'requires tuples of length 2' in str(e):
        arr = pd.arrays.IntervalArray.from_tuples([t[:2] for t in data])
    else:
        raise

Prevention

When it happens

Trigger: `IntervalArray.from_tuples([(0,1,2)])` (length 3); `from_tuples([(0,)])` (length 1); tuples built by zipping three iterables.

Common situations: Malformed upstream data producing 3-tuples; bugs in tuple construction; passing rows of a 3+ column DataFrame as the sequence.

Related errors


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

Appendix: 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 3b7651241d)