pola-rs/polars · error · TypeError

invalid input for `col` Expected iterable of type `str` or

Error message

invalid input for `col`

Expected iterable of type `str` or `DataType`, got iterable of type {type(item).__name__!r}.

What it means

When pl.col receives an iterable, it dispatches on the type of the first element: all-str means a name selector, dtype or Python class means a dtype selector. If the first element is neither a str, a Polars dtype, nor a class, this TypeError names the offending element type. Note that only the first element is inspected for dispatch — mixed lists can still misbehave.

Source

Thrown at py-polars/src/polars/functions/col.py:110

                expand_patterns=True,
            ).as_expr()
        elif is_polars_dtype(item):
            dtypes = []
            for nm in names:
                dtypes.extend(_polars_dtype_match(nm))  # type: ignore[arg-type]
            return pl.Selector._by_dtype(dtypes).as_expr()  # type: ignore[arg-type]
        elif isinstance(item, type):
            dtypes = []
            for nm in names:
                dtypes.extend(_python_dtype_match(nm))  # type: ignore[arg-type]
            return pl.Selector._by_dtype(dtypes).as_expr()  # type: ignore[arg-type]
        else:
            msg = (
                "invalid input for `col`"
                "\n\nExpected iterable of type `str` or `DataType`,"
                f" got iterable of type {type(item).__name__!r}."
            )
            raise TypeError(msg)
    else:
        msg = (
            "invalid input for `col`"
            f"\n\nExpected `str` or `DataType`, got {type(name).__name__!r}."
        )
        raise TypeError(msg)


if sys.version_info >= (3, 11):
    # note: using `co_qualname` is more robust; can additionally
    # detect class scope from inside classmethods and staticmethods...
    def _get_class_objname(f: FrameType) -> str:
        return f.f_code.co_qualname.split(".")[-2:][0]

    _have_qualname = True
else:
    # ... but it's not available until 3.11
    def _get_class_objname(f: FrameType) -> str:

View on GitHub (pinned to df599052da)

Solutions

  1. Convert entries to strings: pl.col([str(c) for c in cols])
  2. Map positions to real names via df.columns[i] before calling pl.col
  3. For dtype selection pass actual dtype objects: pl.col([pl.Int64, pl.Float64])
  4. Keep name lists homogeneous str from the start

Example fix

# before
pl.col([0, 1, 2])

# after
pl.col([df.columns[i] for i in (0, 1, 2)])
# or simply
pl.col(['a', 'b', 'c'])
Defensive patterns

Strategy: type-guard

Validate before calling

cols = [str(c) for c in raw_cols]
if not all(isinstance(c, str) for c in cols):
    raise TypeError('pl.col iterable items must be str or dtypes')
expr = pl.col(cols)

Type guard

def is_homogeneous_name_list(xs: object) -> bool:
    return isinstance(xs, (list, tuple)) and bool(xs) and all(isinstance(x, str) for x in xs)

Prevention

When it happens

Trigger: pl.col([1, 2, 3]); pl.col([None]); pl.col([b'a']) (bytes names); pl.col((1,)) tuple of indices; iterators whose first yielded value is not a str.

Common situations: Passing column indices instead of names (pandas/NumPy habit); bytes column names from serialized sources; lists built by appending an int sentinel first; empty-then-filled lists from loops.

Related errors


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