pola-rs/polars · error · TypeError

invalid type for `on_columns` argument: {qualified_type_name

Error message

invalid type for `on_columns` argument: {qualified_type_name(on_columns)!r}

What it means

In LazyFrame.pivot, `on_columns` supplies the values to pivot on (an iterable of values, a pl.Series, or a pl.DataFrame). A bare `str` is explicitly rejected with TypeError because a string is itself a Sequence and would otherwise be silently iterated character-by-character, producing a wrong pivot.

Source

Thrown at py-polars/src/polars/lazyframe/frame.py:8695

                    version="0.20.5",
                )
                agg = agg.len()
            else:
                msg = f"invalid input for `aggregate_function` argument: {aggregate_function!r}"
                raise ValueError(msg)
        elif aggregate_function is None:
            agg = agg.item(allow_empty=True)
        else:
            agg = aggregate_function

        on_cols: pl.DataFrame
        if isinstance(on_columns, pl.DataFrame):
            on_cols = on_columns
        elif isinstance(on_columns, pl.Series):
            on_cols = on_columns.to_frame()
        elif isinstance(on_columns, str):
            msg = f"invalid type for `on_columns` argument: {qualified_type_name(on_columns)!r}"
            raise TypeError(msg)
        else:
            on_cols = pl.Series(values=on_columns).to_frame()

        return self._from_pyldf(
            self._ldf.pivot(
                on=on_selector._pyselector,
                on_columns=on_cols._df,
                index=index_selector._pyselector,
                values=values_selector._pyselector,
                agg=agg._pyexpr,
                maintain_order=maintain_order,
                separator=separator,
                column_naming=column_naming,
            )
        )

    def unpivot(
        self,

View on GitHub (pinned to df599052da)

Solutions

  1. Wrap the string in a list: on_columns=['a']
  2. Pass a pl.Series or pl.DataFrame holding the pivot values: on_columns=pl.Series(['a','b'])
  3. If you meant a column of the frame to pivot on, pass it to `on`, not `on_columns`

Example fix

// before
lf.pivot('subject', on_columns='maths', values=cs.starts_with('test'))

// after
lf.pivot('subject', on_columns=['maths'], values=cs.starts_with('test'))
Defensive patterns

Strategy: type-guard

Validate before calling

from collections.abc import Sequence
if isinstance(on_columns, str):
    on_columns = [on_columns]  # or raise your own error with context

Type guard

import polars as pl
from collections.abc import Sequence

def is_valid_on_columns(x) -> bool:
    return isinstance(x, (pl.Series, pl.DataFrame)) or (
        isinstance(x, Sequence) and not isinstance(x, str)
    )

Prevention

When it happens

Trigger: Calling lf.pivot('col', on_columns='a', ...) with a single string instead of a list; passing a column-name string to `on_columns` (the new-style value parameter) instead of `on` (the column selector).

Common situations: Migrating from older pivot signatures where string column names were the norm; confusion between `on` (which column to pivot) and `on_columns` (which values appear as new columns); passing a single value without wrapping it.

Related errors


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