pandas-dev/pandas · error · TypeError
dtype must be an IntervalDtype, got {dtype}
Error message
dtype must be an IntervalDtype, got {dtype} What it means
Raised by IntervalArray._ensure_simple_new_inputs (via _simple_new validation) when a dtype is supplied but, after pandas_dtype resolution, it is not an IntervalDtype. Interval arrays require an IntervalDtype subtype; any other dtype (int64, float64, category, etc.) is rejected. TypeError echoing the bad dtype.
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 71959b8cb9)
Solutions
- Use an IntervalDtype, e.g. dtype='interval[int64]' or dtype=pd.IntervalDtype('int64').
- Omit dtype and let pandas infer it from the interval data.
- To change the bound precision, set the subtype inside the IntervalDtype string, not as a bare dtype.
Example fix
# before pd.IntervalIndex.from_breaks([0, 1, 2], dtype='int64') # after pd.IntervalIndex.from_breaks([0, 1, 2], dtype='interval[int64]')
Defensive patterns
Strategy: validation
Validate before calling
def validate_interval_dtype(dtype):
if dtype is not None and not isinstance(pd.api.pandas_dtype(dtype), pd.IntervalDtype):
raise TypeError(f'dtype must be IntervalDtype, got {dtype!r}')
return dtype Type guard
def is_interval_dtype(dtype) -> bool:
return isinstance(pd.api.pandas_dtype(dtype), pd.IntervalDtype) if dtype is not None else False Prevention
- Use 'interval[subtype]' strings for interval arrays.
- Don't pass the inner bound dtype as the array dtype.
- Let pandas infer dtype when unsure.
When it happens
Trigger: pd.arrays.IntervalArray(data, dtype='int64'); pd.IntervalIndex(..., dtype='float64'); passing a numeric or extension dtype that is not an IntervalDtype.
Common situations: Confusing the subtype (the inner numeric dtype) with the array dtype; passing the underlying bound dtype instead of 'interval[...]'.
Related errors
- {cls.__name__}(...) must be called with a collection of some
- Column {colname} must have a numeric dtype. Found '{dtype}'
- No masked accumulation defined for dtype {values.dtype.type}
- DatetimeIndex has mixed timezones
- dtype {data.dtype} cannot be converted to datetime64[ns]
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/32d9f5ed4ebd86ec.
Report an issue: GitHub.