pola-rs/polars · error · TypeError

cannot treat Series of type {s.dtype} as indices

Error message

cannot treat Series of type {s.dtype} as indices

What it means

_convert_series_to_indices (getitem.py:363) accepts only integer Series as positional row indices; a Boolean Series deliberately routes to the boolean-mask error, and any other dtype (float, String, temporal, categorical) cannot be interpreted as positions and raises this TypeError naming s.dtype.

Source

Thrown at py-polars/src/polars/_utils/getitem.py:363

    #   - pl.UInt32 (polars) or pl.UInt64 (polars_u64_idx) Series indexes.
    #   - Other unsigned Series indexes are converted to pl.UInt32 (polars)
    #     or pl.UInt64 (polars_u64_idx).
    #   - Signed Series indexes are converted pl.UInt32 (polars) or
    #     pl.UInt64 (polars_u64_idx) after negative indexes are converted
    #     to absolute indexes.

    # pl.UInt32 (polars) or pl.UInt64 (polars_u64_idx).
    idx_type = get_index_type()

    if s.dtype == idx_type:
        return s

    if not s.dtype.is_integer():
        if s.dtype == Boolean:
            _raise_on_boolean_mask()
        else:
            msg = f"cannot treat Series of type {s.dtype} as indices"
            raise TypeError(msg)

    if s.len() == 0:
        return pl.Series(s.name, [], dtype=idx_type)

    if idx_type == UInt32:
        if s.dtype in {Int64, UInt64} and s.max() >= U32_MAX:  # type: ignore[operator]
            msg = "index positions should be smaller than 2^32"
            raise ValueError(msg)
        if s.dtype == Int64 and s.min() < -U32_MAX:  # type: ignore[operator]
            msg = "index positions should be greater than or equal to -2^32"
            raise ValueError(msg)

    if s.dtype.is_signed_integer():
        if s.min() < 0:  # type: ignore[operator]
            if idx_type == UInt32:
                idxs = s.cast(Int32) if s.dtype in {Int8, Int16} else s
            else:
                idxs = s.cast(Int64) if s.dtype in {Int8, Int16, Int32} else s

View on GitHub (pinned to df599052da)

Solutions

  1. Cast to integer positions: df[idx.cast(pl.Int64)] (round first if fractional: idx.round(0).cast(pl.Int64))
  2. For value-based row selection use df.filter(pl.col('id').is_in(values)) or a join
  3. For name-based selection of columns, put the string Series in the column slot or use df.select(names)

Example fix

# before
df[pl.Series([1.0, 2.0])]  # float Series cannot be indices

# after
df[pl.Series([1.0, 2.0]).cast(pl.Int64)]
Defensive patterns

Strategy: type-guard

Validate before calling

if not idx.dtype.is_integer():
    if idx.dtype == pl.Boolean:
        raise TypeError("use df.filter(mask) for boolean row masks")
    idx = idx.cast(pl.Int64)
df[idx]

Type guard

import polars as pl

def is_index_series(s: pl.Series) -> bool:
    return s.dtype.is_integer()

Prevention

When it happens

Trigger: df[pl.Series(['a', 'b'])] (attempting label-based row selection); df[pl.Series([0.5, 1.0])] (float indices); s[pl.Series(['x'])] on a Series; passing an uncapped result of np.argmax-like computations held in a float Series.

Common situations: Expecting pandas .loc label semantics; using a float column of computed indices without casting; passing a string column of keys instead of using is_in.

Related errors


AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16). Data as JSON: /api/errors/259c66ee6192039f. Report an issue: GitHub.