{"record":{"id":"097377ed10832f1a","repo":"pandas-dev/pandas","slug":"category-object-and-string-subtypes-are-not-supp","errorCode":null,"errorMessage":"category, object, and string subtypes are not supported for IntervalArray","messagePattern":"category, object, and string subtypes are not supported for IntervalArray","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/interval.py","lineNumber":334,"sourceCode":"            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            )\n            raise ValueError(msg)\n        if (\n            isinstance(left.dtype, CategoricalDtype)\n            or is_string_dtype(left.dtype)\n            or is_string_dtype(right.dtype)\n        ):\n            # GH 19016, GH 66518: reject unsupported right-side dtypes too.\n            msg = (\n                \"category, object, and string subtypes are not supported \"\n                \"for IntervalArray\"\n            )\n            raise TypeError(msg)\n        if isinstance(left, ABCPeriodIndex):\n            msg = \"Period dtypes are not supported, use a PeriodIndex instead\"\n            raise ValueError(msg)\n        if isinstance(left, ABCDatetimeIndex) and str(left.tz) != str(right.tz):\n            msg = (\n                \"left and right must have the same time zone, got \"\n                f\"'{left.tz}' and '{right.tz}'\"\n            )\n            raise ValueError(msg)\n        elif needs_i8_conversion(left.dtype) and left.unit != right.unit:\n            # e.g. m8[s] vs m8[ms], try to cast to a common dtype GH#55714\n            left_arr, right_arr = left._data._ensure_matching_resos(right._data)\n            left = ensure_index(left_arr)\n            right = ensure_index(right_arr)\n\n        # For dt64/td64 we want DatetimeArray/TimedeltaArray instead of ndarray\n        left = ensure_wrapped_if_datetimelike(left)\n        left = extract_array(left, extract_numpy=True)","sourceCodeStart":316,"sourceCodeEnd":352,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/arrays/interval.py#L316-L352","documentation":"Raised when the inferred/computed left or right dtype is categorical, object, or string. IntervalArray only supports numeric, datetime, timedelta subtypes; category/object/string endpoints are explicitly rejected (GH 19016, GH 66518 extended the check to the right side too).","triggerScenarios":"Passing Python strings as endpoints (`IntervalArray.from_arrays(['a','b'],['c','d'])`); a column read as `object` or `string` dtype; categorical endpoints from groupby keys; mixed-type object arrays that survived `maybe_convert_objects`.","commonSituations":"Loading intervals from CSV where bounds come in as text; user assuming string-typed intervals (like IP ranges) are supported; constructing from a categorical feature engineered into bins.","solutions":["Convert endpoints to a supported numeric/datetime dtype first: `.astype('int64')`, `.astype('float64')`, or `pd.to_datetime`.","If intervals are genuinely string-bounded, store them as object tuples or use a different structure (IntervalArray will not accept them).","Strip the categorical: `.astype('object').astype('int64')` or use the underlying codes if the category is numeric."],"exampleFix":"# before\nIntervalArray.from_arrays(['a','b'], ['c','d'])\n\n# after - encode as numeric if meaningful\nIntervalArray.from_arrays(pd.Series(['a','b']).astype('category').cat.codes, pd.Series(['c','d']).astype('category').cat.codes)","handlingStrategy":"validation","validationCode":"import pandas as pd\nfrom pandas.api.types import is_string_dtype, is_categorical_dtype\n\ndef bounds_have_supported_dtype(left, right):\n    bad = (is_categorical_dtype(left.dtype) or is_string_dtype(left.dtype)\n           or is_string_dtype(right.dtype) or left.dtype == object)\n    return not bad","typeGuard":"import numpy as np\n\ndef is_supported_interval_subtype(arr) -> bool:\n    k = getattr(arr.dtype, 'kind', None)\n    return k in 'iuf' or isinstance(arr.dtype, np.dtype) and arr.dtype.kind in 'Mm'","tryCatchPattern":"try:\n    arr = IntervalArray.from_arrays(left, right)\nexcept TypeError as e:\n    if 'subtypes are not supported' in str(e):\n        left = pd.to_numeric(pd.Series(left))\n        right = pd.to_numeric(pd.Series(right))\n        arr = IntervalArray.from_arrays(left, right)\n    else:\n        raise","preventionTips":["Cast object/string endpoints to numeric or datetime before constructing.","Decategoricalise with .cat.codes if categories are numeric.","Validate endpoint dtypes at ingestion in ETL pipelines."],"tags":["interval","unsupported-dtype","string-subtype","categorical","type-error"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}