pola-rs/polars · error · InvalidOperationError
`pivot` needs either `index or `values` needs to be specifie
Error message
`pivot` needs either `index or `values` needs to be specified
What it means
LazyFrame.pivot() requires at least one of index= or values= to be given (on= is mandatory separately). If neither is provided, polars cannot decide which columns become the row identifiers versus the pivoted values, and raises InvalidOperationError. When only one is given, the other is inferred as the complement of the on= columns.
Source
Thrown at py-polars/src/polars/lazyframe/frame.py:8651
╞══════╪══════════╪══════════╡
│ a ┆ 0.998347 ┆ null │
│ b ┆ 0.964028 ┆ 0.999954 │
└──────┴──────────┴──────────┘
""" # noqa: W505
on_selector = parse_list_into_selector(on)
if index is not None and values is not None:
index_selector = parse_list_into_selector(index)
values_selector = parse_list_into_selector(values)
elif index is not None:
index_selector = parse_list_into_selector(index)
values_selector = cs.all() - on_selector - index_selector
elif values is not None:
values_selector = parse_list_into_selector(values)
index_selector = cs.all() - on_selector - values_selector
else:
msg = "`pivot` needs either `index or `values` needs to be specified"
raise InvalidOperationError(msg)
agg = F.element()
if isinstance(aggregate_function, str):
if aggregate_function == "first":
agg = agg.first()
elif aggregate_function == "item":
agg = agg.item()
elif aggregate_function == "sum":
agg = agg.sum()
elif aggregate_function == "max":
agg = agg.max()
elif aggregate_function == "min":
agg = agg.min()
elif aggregate_function == "mean":
agg = agg.mean()
elif aggregate_function == "median":
agg = agg.median()
elif aggregate_function == "last":View on GitHub (pinned to df599052da)
Solutions
- Pass index=['id'] to identify output rows, letting values default to all remaining non-on columns
- Or pass values=['val'] to pivot explicitly, letting index default to the complement
- Validate config: require at least one of index/values before calling pivot
- Check for typos — the argument names are exactly 'index' and 'values'
Example fix
# before wide = lf.pivot(on='month') # after wide = lf.pivot(on='month', index='id', aggregate_function='sum')
Defensive patterns
Strategy: validation
Validate before calling
if index is None and values is None:
index = ['id'] # sensible default row identifier
wide = lf.pivot(on=on, index=index, values=values, aggregate_function=aggregate_function) Type guard
def has_pivot_axes(index, values) -> bool:
return index is not None or values is not None Try / catch
try:
wide = lf.pivot(on='month')
except Exception:
wide = lf.pivot(on='month', index='id', aggregate_function='sum') Prevention
- Always pass index= explicitly in config-driven pivots
- Validate reshape config before running the pipeline
- Remember on= is required and handles column grouping, not row identity
When it happens
Trigger: lf.pivot(on='metric', values=... missing and index missing); dynamic pipelines where index/values come from config that is empty; porting DataFrame.pivot calls that had different parameter requirements.
Common situations: Config-driven reshaping jobs; wide/long transformations where the caller assumed column inference from on= alone.
Related errors
- you should pass the column to join on as an argument
- 'left_on' requires corresponding 'right_on'
- must specify `on` OR `left_on` and `right_on`
- invalid input for `aggregate_function` argument: {aggregate_
- invalid type for `on_columns` argument: {qualified_type_name
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/f798018947f82f83.
Report an issue: GitHub.