pandas-dev/pandas · error · TypeError

{name}.from_tuples received an invalid item, {d}

Error message

{name}.from_tuples received an invalid item, {d}

What it means

Raised by `from_tuples` when unpacking an entry raises TypeError — meaning the entry is not iterable at all (e.g., an int, float, or scalar). Each item must be a length-2 tuple (or NaN/None). Fires at pandas/core/arrays/interval.py:589.

Source

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

            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
        * left is always below right
        """
        if not isinstance(dtype, IntervalDtype):

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. If you have flat bounds, use `IntervalIndex.from_arrays(left_list, right_list)` instead.
  2. Map scalars into pairs explicitly if that was the intent: `[(x, x) for x in data]`.
  3. Filter non-tuple entries: `[t for t in data if isinstance(t, tuple)]`.

Example fix

// before
pd.IntervalIndex.from_tuples(bounds_series)
// after
pd.IntervalIndex.from_arrays(left_series, right_series)
Defensive patterns

Strategy: type-guard

Validate before calling

def ensure_pair_list(data):
    import numpy as np
    out = []
    for d in data:
        if isinstance(d, tuple):
            out.append(d)
        elif d is None or (isinstance(d, float) and np.isnan(d)):
            out.append((np.nan, np.nan))
        else:
            raise TypeError(f"item is not a tuple: {d!r}")
    return out

Type guard

import numpy as np

def is_pair_or_na(d) -> bool:
    return isinstance(d, tuple) or d is None or (isinstance(d, float) and np.isnan(d))

Try / catch

try:
    ii = pd.IntervalIndex.from_tuples(data)
except TypeError as e:
    if "invalid item" in str(e):
        # caller probably has flat bounds
        raise TypeError("from_tuples needs tuples; use from_arrays(left, right) instead") from e
    raise

Prevention

When it happens

Trigger: `pd.IntervalIndex.from_tuples([0, 1, 2])`, `from_tuples([pd.NA, (1,2)])` (NA handled but a scalar int is not), or passing a flat list of numbers.

Common situations: Passing a list of scalars when intervals were intended; passing already-split single bounds; misreading API and passing a Series of values instead of tuples.

Related errors


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