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 exprView on GitHub (pinned to df599052da)
Solutions
- Pass column names: df.unique(subset=['a', 'b'])
- Pass selector expressions: df.unique(subset=cs.numeric()) or df.unique(subset=pl.col('label').str.extract(r'^(\w+):'))
- 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
- Pass column names or cs-Selectors to unique(subset=...), never positions or Series
- Convert Series with .to_list() at the boundary
- Type-annotate subset parameters as Sequence[str | pl.Expr] to catch regressions
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
- cannot turn {qualified_type_name(i)!r} into selector
- Cannot pass a dictionary as a single positional argument.\nI
- cannot select columns using key of type {qualified_type_name
- cannot select rows using key of type {qualified_type_name(ke
- cannot treat Series of type {s.dtype} as indices
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/7104bf1a6a1db1f6.
Report an issue: GitHub.