pola-rs/polars · error · TypeError

invalid type for `on_columns` argument

Error message

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

What it means

Raised as a TypeError when the `on_columns` argument of LazyFrame.pivot is a plain string. This parameter expects a DataFrame, Series, or an iterable of values — a lone string is ambiguous and explicitly rejected.

Solutions

  1. Wrap the string in a list: `on_columns=["colname"]`.
  2. Or pass a `pl.Series`/`pl.DataFrame` containing the desired values.
  3. Use `on=` (a selector) instead if that was the intended parameter.

Example fix

// before
lf.pivot(on="date", on_columns="region")
// after
lf.pivot(on="date", on_columns=["region"])
Defensive patterns

Strategy: type-guard

Validate before calling

if isinstance(on_columns, str):
    on_columns = [on_columns]
out = lf.pivot(on=on, on_columns=on_columns)

Type guard

def is_pivot_on_columns(v) -> bool:
    return isinstance(v, (pl.DataFrame, pl.Series, list, tuple)) and not isinstance(v, str)

Try / catch

try:
    out = lf.pivot(on=on, on_columns=on_columns)
except TypeError as e:
    if "on_columns" in str(e):
        out = lf.pivot(on=on, on_columns=[on_columns])
    else:
        raise

Prevention

When it happens

Trigger: Calling `lf.pivot(on=..., on_columns="colname")` — the isinstance chain (DataFrame, Series, str) hits the str branch and raises.

Common situations: Passing a single column name as a string by analogy with `on=`; mixing up the `on` and `on_columns` parameters.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

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

            elif aggregate_function == "count":
                msg = "use of `aggregate_function='count'` should be replaced with `aggregate_function='len'`."
                raise ValueError(msg)
            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,
            )
        )

    @removed_parameters(
        RemovedParameter(name="streamable", deprecated_in="1.5.0", removed_in="2.0")

View on GitHub (pinned to fe841f959e)