{"record":{"id":"edbe72ccf340b626","repo":"pola-rs/polars","slug":"cannot-use-series-of-dtype-key-dtype-r-for-index","errorCode":null,"errorMessage":"cannot use Series of dtype {key.dtype!r} for indexing; expected boolean or integer dtype","messagePattern":"cannot use Series of dtype (.+?) for indexing; expected boolean or integer dtype","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/series/series.py","lineNumber":1555,"sourceCode":"            self.scatter(key, value)\n            return None\n        elif isinstance(value, Sequence) and not isinstance(value, str):\n            if self.dtype.is_numeric() or self.dtype.is_temporal():\n                self.scatter(key, value)  # type: ignore[arg-type]\n                return None\n            msg = (\n                f\"cannot set Series of dtype: {self.dtype!r} with list/tuple as value;\"\n                \" use a scalar value\"\n            )\n            raise TypeError(msg)\n        if isinstance(key, Series):\n            if key.dtype == Boolean:\n                self._s = self.set(key, value)._s\n            elif key.dtype.is_integer():\n                self._s = self.scatter(key, value)._s\n            else:\n                msg = f\"cannot use Series of dtype {key.dtype!r} for indexing; expected boolean or integer dtype\"\n                raise TypeError(msg)\n\n        # TODO: implement for these types without casting to series\n        elif _check_for_numpy(key) and isinstance(key, np.ndarray):\n            if key.dtype == np.bool_:\n                # boolean numpy mask\n                self._s = self.scatter(np.argwhere(key)[:, 0], value)._s\n            else:\n                s = self._from_pyseries(\n                    PySeries.new_u32(\"\", np.array(key, np.uint32), _strict=True)\n                )\n                self.__setitem__(s, value)\n        elif isinstance(key, (list, tuple)):\n            s = self._from_pyseries(sequence_to_pyseries(\"\", key, dtype=UInt32))\n            self.__setitem__(s, value)\n        else:\n            msg = f'cannot use \"{key!r}\" for indexing'\n            raise TypeError(msg)\n","sourceCodeStart":1537,"sourceCodeEnd":1573,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/series/series.py#L1537-L1573","documentation":"Raised by Series.__setitem__ when the indexing key is a Series whose dtype is neither Boolean (mask) nor integer (positions). The setter supports exactly two key kinds - boolean masks for conditional assignment and integer Series for positional scatter - and rejects anything else, including float index Series and string Series.","triggerScenarios":"`s[key_series] = value` where key.dtype is e.g. Float64 (`pl.Series([0.0, 1.0])`), String, or another non-Boolean/non-integer type. Note floats do NOT count as integer: `s[pl.Series([1.5])] = 0` and `s[pl.Series(np.linspace(0, 1, n))] = 0` both raise.","commonSituations":"Indices produced by numpy float arithmetic (np.linspace, normalized positions, division results) fed directly as keys; passing a string column expecting label-based indexing (pandas `.loc` habit); float masks computed as proportions instead of booleans.","solutions":["Cast the key to the intended kind: `s[key.cast(pl.Int64)] = v` for positions, `s[key.cast(pl.Boolean)] = v` for masks.","Build integer indices explicitly: `pl.Series(range(n), dtype=pl.Int64)` or `np.argwhere(mask).squeeze()`.","Use a Python list of ints, which is converted internally: `s[[0, 1]] = v`.","For condition-based updates prefer `pl.when(...).then(...)` at the frame level."],"exampleFix":"// before\ns = pl.Series([1, 2, 3])\nidx = pl.Series([0.0, 2.0])\ns[idx] = 0  # TypeError\n\n// after\ns[idx.cast(pl.Int64)] = 0\n# or\ns[[0, 2]] = 0","handlingStrategy":"validation","validationCode":"def valid_key_series(k: pl.Series) -> bool:\n    return k.dtype == pl.Boolean or k.dtype.is_integer()\n\nif isinstance(key, pl.Series):\n    assert valid_key_series(key), f'bad key dtype {key.dtype}'","typeGuard":"def is_valid_index_series(k: pl.Series) -> bool:\n    return k.dtype == pl.Boolean or k.dtype.is_integer()","tryCatchPattern":"try:\n    s[key] = value\nexcept TypeError as e:\n    if 'expected boolean or integer dtype' not in str(e):\n        raise\n    s[key.cast(pl.Int64) if key.dtype.is_float() else key.cast(pl.Boolean)] = value","preventionTips":["Cast float indices to Int64 before use: key.cast(pl.Int64).","numpy position outputs (np.argwhere, np.where) are integers - prefer them over hand-computed floats.","Polars Series have no label-based indexing; never pass string columns as keys."],"tags":["polars","series","setitem","indexing","dtype","boolean-mask"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}