pandas-dev/pandas · error · TypeError

dtype must be an IntervalDtype, got

Error message

dtype must be an IntervalDtype, got {dtype}

What it means

Raised in `IntervalArray._ensure_simple_new_inputs` when an explicit `dtype` is given but, after `pandas_dtype(dtype)`, it is not an `IntervalDtype`. To override the inferred subtype you must pass a dtype that resolves to IntervalDtype (e.g. `'interval[int64]'`, `IntervalDtype('int64')`); a plain `'int64'` is the underlying subtype, not the array dtype.

Solutions

  1. Wrap the subtype in IntervalDtype: `dtype='interval[int64]'` or `dtype=IntervalDtype(np.int64)`.
  2. Omit dtype entirely and let pandas infer the subtype from left/right.
  3. If you only need to coerce the subtype, cast left/right beforehand with `.astype(np.int64)` and pass dtype=None.

Example fix

# before
pd.arrays.IntervalArray.from_arrays([0,1],[1,2], dtype='int64')

# after
pd.arrays.IntervalArray.from_arrays([0,1],[1,2], dtype='interval[int64]')
# or omit dtype
pd.arrays.IntervalArray.from_arrays([0,1],[1,2])
Defensive patterns

Strategy: validation

Validate before calling

import pandas as pd
from pandas import IntervalDtype

def interval_dtype_or_none(dtype):
    if dtype is None:
        return None
    d = pd.api.types.pandas_dtype(dtype)
    if not isinstance(d, IntervalDtype):
        # wrap the subtype
        return IntervalDtype(dtype)
    return d

Type guard

from pandas import IntervalDtype
import pandas as pd

def is_interval_dtype_spec(dtype) -> bool:
    if dtype is None:
        return True
    try:
        return isinstance(pd.api.types.pandas_dtype(dtype), IntervalDtype)
    except TypeError:
        return False

Try / catch

try:
    arr = pd.arrays.IntervalArray.from_arrays(l, r, dtype=dtype)
except TypeError as e:
    if 'dtype must be an IntervalDtype' in str(e):
        arr = pd.arrays.IntervalArray.from_arrays(l, r, dtype=f'interval[{dtype}]')
    else:
        raise

Prevention

When it happens

Trigger: Calling `IntervalArray.from_arrays(left, right, dtype='int64')` expecting it to set the subtype; passing `dtype=np.float64` or `dtype='float'` directly instead of `'interval[float64]'`; using a string that pandas_dtype resolves to a non-Interval dtype.

Common situations: Users familiar with numeric Index dtypes assuming the same string works for intervals; constructing from read_csv dtypes; copy-pasting subtype dtype where the wrapper dtype is required.

Related errors


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

Appendix: source

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

        left = ensure_index(left, copy=copy)

        right = ensure_index(right, copy=copy)

        if closed is None and isinstance(dtype, IntervalDtype):
            closed = dtype.closed

        closed = closed or "right"

        if dtype is not None:
            # GH 19262: dtype must be an IntervalDtype to override inferred
            dtype = pandas_dtype(dtype)
            if isinstance(dtype, IntervalDtype):
                if dtype.subtype is not None:
                    left = left.astype(dtype.subtype)
                    right = right.astype(dtype.subtype)
            else:
                msg = f"dtype must be an IntervalDtype, got {dtype}"
                raise TypeError(msg)

            if dtype.closed is None:
                # possibly loading an old pickle
                dtype = IntervalDtype(dtype.subtype, closed)
            elif closed != dtype.closed:
                raise ValueError("closed keyword does not match dtype.closed")

        # coerce dtypes to match if needed
        if is_float_dtype(left.dtype) and is_integer_dtype(right.dtype):
            right = right.astype(left.dtype)
        elif is_float_dtype(right.dtype) and is_integer_dtype(left.dtype):
            left = left.astype(right.dtype)

        if type(left) != type(right):
            msg = (
                f"must not have differing left [{type(left).__name__}] and "
                f"right [{type(right).__name__}] types"
            )

View on GitHub (pinned to 3b7651241d)