{"record":{"id":"04c547944298f1e2","repo":"pandas-dev/pandas","slug":"closed-keyword-does-not-match-dtype-closed","errorCode":null,"errorMessage":"closed keyword does not match dtype.closed","messagePattern":"closed keyword does not match dtype\\.closed","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/interval.py","lineNumber":310,"sourceCode":"\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            )\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        ):","sourceCodeStart":292,"sourceCodeEnd":328,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/arrays/interval.py#L292-L328","documentation":"Raised in `_ensure_simple_new_inputs` when both an explicit `closed` keyword and an explicit `IntervalDtype` with a non-None `.closed` are passed, and they disagree (e.g. `closed='left'` with `dtype='interval[int64, right]'`). The closed attribute lives on the dtype, so pandas refuses a contradictory override.","triggerScenarios":"Passing `IntervalArray.from_arrays(left, right, closed='left', dtype=IntervalDtype('int64', 'right'))`; loading an old pickle whose dtype carries closed='right' while constructing with closed='left'.","commonSituations":"Building intervals interactively and toggling closed; serialised dtype carrying closed state recombined with a different keyword; refactoring where closed was moved into the dtype string.","solutions":["Make closed consistent: specify it in only one place — either the keyword or the dtype.","If the dtype came from an old pickle (closed is None), the keyword is used to fill it; do not pass a closed keyword when the dtype already carries one.","Construct the dtype with matching closed: `IntervalDtype('int64', 'left')` together with `closed='left'`."],"exampleFix":"# before\nIntervalArray.from_arrays(l, r, closed='left', dtype=IntervalDtype('int64', 'right'))\n\n# after - choose one source of truth\nIntervalArray.from_arrays(l, r, closed='left')\n# or\nIntervalArray.from_arrays(l, r, dtype=IntervalDtype('int64', 'left'))","handlingStrategy":"validation","validationCode":"from pandas import IntervalDtype\n\ndef reconcile_closed(dtype, closed):\n    if isinstance(dtype, IntervalDtype) and dtype.closed is not None:\n        if closed is not None and closed != dtype.closed:\n            raise ValueError(f'closed={closed} conflicts with dtype.closed={dtype.closed}')\n        return dtype.closed\n    return closed","typeGuard":"from pandas import IntervalDtype\n\ndef closed_is_consistent(dtype, closed) -> bool:\n    if isinstance(dtype, IntervalDtype) and dtype.closed is not None and closed is not None:\n        return dtype.closed == closed\n    return True","tryCatchPattern":"try:\n    arr = IntervalArray.from_arrays(l, r, closed=closed, dtype=dtype)\nexcept ValueError as e:\n    if 'closed keyword does not match' in str(e):\n        arr = IntervalArray.from_arrays(l, r, dtype=dtype)  # let dtype win\n    else:\n        raise","preventionTips":["Specify closed in exactly one place (keyword OR dtype), never both with different values.","When loading pickled IntervalDtype, do not also pass a closed keyword.","Add a unit test asserting closed consistency when constructing from external config."],"tags":["interval","closed-attribute","dtype-conflict","value-error"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}