{"record":{"id":"32d9f5ed4ebd86ec","repo":"pandas-dev/pandas","slug":"dtype-must-be-an-intervaldtype-got-dtype","errorCode":null,"errorMessage":"dtype must be an IntervalDtype, got {dtype}","messagePattern":"dtype must be an IntervalDtype, got (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/interval.py","lineNumber":304,"sourceCode":"        left = ensure_index(left, copy=copy)\n\n        right = ensure_index(right, copy=copy)\n\n        if closed is None and isinstance(dtype, IntervalDtype):\n            closed = dtype.closed\n\n        closed = closed or \"right\"\n\n        if dtype is not None:\n            # GH 19262: dtype must be an IntervalDtype to override inferred\n            dtype = pandas_dtype(dtype)\n            if isinstance(dtype, IntervalDtype):\n                if dtype.subtype is not None:\n                    left = left.astype(dtype.subtype)\n                    right = right.astype(dtype.subtype)\n            else:\n                msg = f\"dtype must be an IntervalDtype, got {dtype}\"\n                raise TypeError(msg)\n\n            if dtype.closed is None:\n                # possibly loading an old pickle\n                dtype = IntervalDtype(dtype.subtype, closed)\n            elif closed != dtype.closed:\n                raise ValueError(\"closed keyword does not match dtype.closed\")\n\n        # coerce dtypes to match if needed\n        if is_float_dtype(left.dtype) and is_integer_dtype(right.dtype):\n            right = right.astype(left.dtype)\n        elif is_float_dtype(right.dtype) and is_integer_dtype(left.dtype):\n            left = left.astype(right.dtype)\n\n        if type(left) != type(right):\n            msg = (\n                f\"must not have differing left [{type(left).__name__}] and \"\n                f\"right [{type(right).__name__}] types\"\n            )","sourceCodeStart":286,"sourceCodeEnd":322,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/arrays/interval.py#L286-L322","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Wrap the subtype in IntervalDtype: `dtype='interval[int64]'` or `dtype=IntervalDtype(np.int64)`.","Omit dtype entirely and let pandas infer the subtype from left/right.","If you only need to coerce the subtype, cast left/right beforehand with `.astype(np.int64)` and pass dtype=None."],"exampleFix":"# before\npd.arrays.IntervalArray.from_arrays([0,1],[1,2], dtype='int64')\n\n# after\npd.arrays.IntervalArray.from_arrays([0,1],[1,2], dtype='interval[int64]')\n# or omit dtype\npd.arrays.IntervalArray.from_arrays([0,1],[1,2])","handlingStrategy":"validation","validationCode":"import pandas as pd\nfrom pandas import IntervalDtype\n\ndef interval_dtype_or_none(dtype):\n    if dtype is None:\n        return None\n    d = pd.api.types.pandas_dtype(dtype)\n    if not isinstance(d, IntervalDtype):\n        # wrap the subtype\n        return IntervalDtype(dtype)\n    return d","typeGuard":"from pandas import IntervalDtype\nimport pandas as pd\n\ndef is_interval_dtype_spec(dtype) -> bool:\n    if dtype is None:\n        return True\n    try:\n        return isinstance(pd.api.types.pandas_dtype(dtype), IntervalDtype)\n    except TypeError:\n        return False","tryCatchPattern":"try:\n    arr = pd.arrays.IntervalArray.from_arrays(l, r, dtype=dtype)\nexcept TypeError as e:\n    if 'dtype must be an IntervalDtype' in str(e):\n        arr = pd.arrays.IntervalArray.from_arrays(l, r, dtype=f'interval[{dtype}]')\n    else:\n        raise","preventionTips":["Use 'interval[subtype]' strings rather than bare subtype strings.","Omit dtype when in doubt and let pandas infer.","Build dtype via IntervalDtype(subtype) in library code."],"tags":["interval","interval-dtype","dtype-validation","type-error"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}