pola-rs/polars · error · TypeError

cannot turn {qualified_type_name(i)!r} into selector

Error message

cannot turn {qualified_type_name(i)!r} into selector

What it means

parse_into_selector (polars/_utils/parse/expr.py:180) turns a single input into a column selector for methods like LazyFrame.drop, drop_nulls/drop_nans subset, group_by, and unpivot (on/index/values). Valid elements are str (glob patterns expanded), pl.Selector, or pl.Expr (converted via meta.as_selector()); any other element type raises this TypeError.

Source

Thrown at py-polars/src/polars/_utils/parse/expr.py:180

def parse_into_selector(
    i: ColumnNameOrSelector,
    *,
    strict: bool = True,
    raise_if_not_selector: bool = True,
) -> pl.Selector | None:
    if isinstance(i, str):
        return pl.Selector._by_name(
            names=[i],
            strict=strict,
            expand_patterns=True,
        )
    elif isinstance(i, pl.Selector):
        return i
    elif isinstance(i, pl.Expr):
        return i.meta.as_selector()
    elif raise_if_not_selector:
        msg = f"cannot turn {qualified_type_name(i)!r} into selector"
        raise TypeError(msg)
    return None


def parse_list_into_selector(
    inputs: ColumnNameOrSelector | Collection[ColumnNameOrSelector],
    *,
    strict: bool = True,
) -> pl.Selector:
    if isinstance(inputs, Collection) and not isinstance(inputs, str):
        columns: list[str] = [i for i in inputs if isinstance(i, str)]
        selector = pl.Selector._by_name(
            names=columns,
            strict=strict,
            expand_patterns=True,
        )
        if len(columns) == len(inputs):
            return selector

View on GitHub (pinned to df599052da)

Solutions

  1. Pass column-name strings: df.drop(['a', 'b'])
  2. Translate positions to names: df.drop([df.columns[i] for i in (0, 1)])
  3. Convert a Series of names: df.drop(names.to_list())

Example fix

# before
df.drop([0, 1])

# after
df.drop([df.columns[i] for i in (0, 1)])
Defensive patterns

Strategy: type-guard

Validate before calling

cols = [df.columns[i] if isinstance(c, int) else c for c in cols]
if not all(isinstance(c, (str, pl.Expr)) for c in cols):
    raise TypeError("expected column names or selector expressions")
df.drop(cols)

Type guard

import polars as pl
from collections.abc import Collection

def is_name_or_selector_list(cols) -> bool:
    return (
        isinstance(cols, Collection)
        and not isinstance(cols, str)
        and all(isinstance(c, (str, pl.Expr)) for c in cols)
    )

Prevention

When it happens

Trigger: df.drop([0, 1]) (integer positions instead of names); df.drop(pl.Series(['a'])); lf.drop_nulls(subset=[0]); lf.unpivot(index=np.array([1, 2], dtype=np.float64)); mixed lists like ['a', 0].

Common situations: Coming from APIs that accept column positions; lists built by appending mixed types; refactors where a Series replaces a list of names.

Related errors


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