pola-rs/polars · error

invalid name: {nm!r}

Error message

invalid name: {nm!r}

What it means

Thrown by cs.by_name (py-polars/src/polars/selectors.py:1295) when a TOP-LEVEL argument is neither a str nor a Collection of str. by_name(*names) accepts "a", ["a", "b"], or mixed str/collection args; an outer item that is an int, None, a dtype, etc. hits the else-branch and raises TypeError.

Source

Thrown at py-polars/src/polars/selectors.py:1295

    │ f64 ┆ bool  │
    ╞═════╪═══════╡
    │ 2.0 ┆ false │
    │ 5.5 ┆ true  │
    └─────┴───────┘
    """
    all_names = []
    for nm in names:
        if isinstance(nm, str):
            all_names.append(nm)
        elif isinstance(nm, Collection):
            for n in nm:
                if not isinstance(n, str):
                    msg = f"invalid name: {n!r}"
                    raise TypeError(msg)
                all_names.append(n)
        else:
            msg = f"invalid name: {nm!r}"
            raise TypeError(msg)

    return Selector._by_name(all_names, strict=require_all, expand_patterns=False)


def empty() -> Selector:
    """
    Select no columns.

    This is useful for composition with other selectors.

    See Also
    --------
    all : Select all columns in the current scope.

    Examples
    --------
    >>> import polars.selectors as cs
    >>> pl.DataFrame({"a": 1, "b": 2}).select(cs.empty())

View on GitHub (pinned to df599052da)

Solutions

  1. Pass names as strings: cs.by_name("a", "b") or a list cs.by_name(["a", "b"])
  2. If you meant position or dtype, use the right selector: cs.by_index(0) or cs.by_dtype(pl.Int64)
  3. Sanitize dynamic lists: cs.by_name([n for n in names if isinstance(n, str)]) or coerce with str()

Example fix

# before
sel = cs.by_name(1)  # int is not a name

# after
sel = cs.by_name("1")
# if a position was intended:
sel = cs.by_index(1)
Defensive patterns

Strategy: type-guard

Validate before calling

def is_name_arg(x: object) -> bool:
    return isinstance(x, str) or (isinstance(x, Collection) and all(isinstance(n, str) for n in x))

assert all(is_name_arg(a) for a in args), f"by_name args invalid: {args!r}"

Type guard

from typing import TypeGuard

def is_name_or_names(x: object) -> TypeGuard[str | list[str]]:
    return isinstance(x, str)

Try / catch

try:
    sel = cs.by_name(*args)
except TypeError as e:
    if "invalid name" in str(e):
        raise ValueError("by_name expects column name strings; use by_index/by_dtype for positions/dtypes") from e
    raise

Prevention

When it happens

Trigger: cs.by_name(1), cs.by_name(None), cs.by_name(pl.Int64) (passing a dtype where a name is expected), or cs.by_name(*cols) where cols contains a non-str element.

Common situations: Passing an index or dtype by mistake (confusing by_name with by_index/by_dtype), or splatting an unvalidated list of identifiers that contains ints or None.

Related errors


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