pola-rs/polars · error · TypeError

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

Error message

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

What it means

parse_into_expression with require_selector=True backs parse_into_list_of_expressions_require_selectors, whose only caller is LazyFrame.unique(subset=...) (lazyframe/frame.py:8275; DataFrame.unique delegates through lazy). Each subset element must be a column name (str) or a selector expression (pl.Expr / pl.Selector); anything else cannot name columns and raises this TypeError instead of being treated as a literal value.

Source

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

        If the input is expected to resolve to a literal with a known dtype, pass
        this to the `lit` constructor.
    require_selector
        Require that the input is a valid selector (eg: column name or selector).

    Returns
    -------
    PyExpr
    """
    if isinstance(input, pl.Expr):
        expr = input
        if structify:
            expr = _structify_expression(expr)
    elif isinstance(input, str) and not str_as_lit:
        expr = F.col(input)
    else:
        if require_selector:
            msg = f"cannot turn {qualified_type_name(input)!r} into selector"
            raise TypeError(msg)
        elif isinstance(input, list) and list_as_series:
            expr = F.lit(pl.Series(input), dtype=dtype)
        else:
            expr = F.lit(input, dtype=dtype)

    return expr._pyexpr


def _structify_expression(expr: Expr) -> Expr:
    unaliased_expr = expr.meta.undo_aliases()
    if unaliased_expr.meta.has_multiple_outputs():
        try:
            expr_name = expr.meta.output_name()
        except ComputeError:
            expr = F.struct(expr)
        else:
            expr = F.struct(unaliased_expr).alias(expr_name)
    return expr

View on GitHub (pinned to df599052da)

Solutions

  1. Pass column names: df.unique(subset=['a', 'b'])
  2. Pass selector expressions: df.unique(subset=cs.numeric()) or df.unique(subset=pl.col('label').str.extract(r'^(\w+):'))
  3. Convert Series to a list: df.unique(subset=names.to_list())

Example fix

# before
df.unique(subset=pl.Series(["a", "b"]))

# after
df.unique(subset=["a", "b"])  # or names.to_list()
Defensive patterns

Strategy: type-guard

Validate before calling

import polars as pl

if isinstance(subset, pl.Series):
    subset = subset.to_list()
if not all(isinstance(s, (str, pl.Expr)) for s in subset):
    raise TypeError("unique subset accepts only column names or expressions")
df.unique(subset=subset)

Type guard

import polars as pl

def is_valid_subset(subset) -> bool:
    if isinstance(subset, (str, pl.Expr)):
        return True
    return isinstance(subset, (list, tuple)) and all(
        isinstance(s, (str, pl.Expr)) for s in subset
    )

Prevention

When it happens

Trigger: df.unique(subset=0) (integer position); df.unique(subset=[0, 1]); df.unique(subset=pl.Series(['a'])); df.unique(subset=some_dict); floats or None inside the subset list.

Common situations: Passing pandas-style integer column positions; passing a Series of names produced upstream; refactoring from select()/drop() call sites where other input types are accepted.

Related errors


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