{"record":{"id":"5f3cd4c8477456cd","repo":"pola-rs/polars","slug":"invalid-type-for-on-columns-argument-qualified","errorCode":null,"errorMessage":"invalid type for `on_columns` argument: {qualified_type_name(on_columns)!r}","messagePattern":"invalid type for `on_columns` argument: (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/lazyframe/frame.py","lineNumber":8695,"sourceCode":"                    version=\"0.20.5\",\n                )\n                agg = agg.len()\n            else:\n                msg = f\"invalid input for `aggregate_function` argument: {aggregate_function!r}\"\n                raise ValueError(msg)\n        elif aggregate_function is None:\n            agg = agg.item(allow_empty=True)\n        else:\n            agg = aggregate_function\n\n        on_cols: pl.DataFrame\n        if isinstance(on_columns, pl.DataFrame):\n            on_cols = on_columns\n        elif isinstance(on_columns, pl.Series):\n            on_cols = on_columns.to_frame()\n        elif isinstance(on_columns, str):\n            msg = f\"invalid type for `on_columns` argument: {qualified_type_name(on_columns)!r}\"\n            raise TypeError(msg)\n        else:\n            on_cols = pl.Series(values=on_columns).to_frame()\n\n        return self._from_pyldf(\n            self._ldf.pivot(\n                on=on_selector._pyselector,\n                on_columns=on_cols._df,\n                index=index_selector._pyselector,\n                values=values_selector._pyselector,\n                agg=agg._pyexpr,\n                maintain_order=maintain_order,\n                separator=separator,\n                column_naming=column_naming,\n            )\n        )\n\n    def unpivot(\n        self,","sourceCodeStart":8677,"sourceCodeEnd":8713,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/lazyframe/frame.py#L8677-L8713","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Wrap the string in a list: on_columns=['a']","Pass a pl.Series or pl.DataFrame holding the pivot values: on_columns=pl.Series(['a','b'])","If you meant a column of the frame to pivot on, pass it to `on`, not `on_columns`"],"exampleFix":"// before\nlf.pivot('subject', on_columns='maths', values=cs.starts_with('test'))\n\n// after\nlf.pivot('subject', on_columns=['maths'], values=cs.starts_with('test'))","handlingStrategy":"type-guard","validationCode":"from collections.abc import Sequence\nif isinstance(on_columns, str):\n    on_columns = [on_columns]  # or raise your own error with context","typeGuard":"import polars as pl\nfrom collections.abc import Sequence\n\ndef is_valid_on_columns(x) -> bool:\n    return isinstance(x, (pl.Series, pl.DataFrame)) or (\n        isinstance(x, Sequence) and not isinstance(x, str)\n    )","tryCatchPattern":null,"preventionTips":["Never pass a bare str where polars accepts Sequence[Any]; strings are sequences and polars guards against char-iteration","Remember the split: `on` selects the frame column, `on_columns` provides the literal pivot values"],"tags":["polars","pivot","lazyframe","type-error"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}