pola-rs/polars · error · TypeError
the `columns` argument should contain a list of all integers
Error message
the `columns` argument should contain a list of all integers or all string values
What it means
polars' parse_columns_arg (py-polars/src/polars/io/_utils.py:60-78) normalizes the `columns` argument of eager readers such as read_csv/read_parquet/read_ipc. It accepts exactly one of: a single str, a single int, a sequence of all strs, or a sequence of all ints. Anything else - a mixed list like [0, 'b'], a set, a dict, or a list containing None - falls into the final else branch and raises this TypeError before any file is opened.
Source
Thrown at py-polars/src/polars/io/_utils.py:76
if columns is None:
return None, None
projection: Sequence[int] | None = None
column_names: Sequence[str] | None = None
if isinstance(columns, str):
column_names = [columns]
elif isinstance(columns, int):
projection = [columns]
elif is_str_sequence(columns):
_ensure_columns_are_unique(columns)
column_names = columns
elif is_int_sequence(columns):
_ensure_columns_are_unique(columns)
projection = columns
else:
msg = "the `columns` argument should contain a list of all integers or all string values"
raise TypeError(msg)
return projection, column_names
def _ensure_columns_are_unique(columns: Sequence[str] | Sequence[int]) -> None:
if len(columns) != len(set(columns)):
msg = f"`columns` arg should only have unique values, got {columns!r}"
raise ValueError(msg)
def parse_row_index_args(
row_index_name: str | None = None,
row_index_offset: int = 0,
) -> tuple[str, int] | None:
"""
Parse the `row_index_name` and `row_index_offset` arguments of an I/O function.
The Rust functions take a single tuple rather than two separate arguments.View on GitHub (pinned to df599052da)
Solutions
- Make `columns` homogeneous: all strings (['a','b']) or all zero-based integer indices ([0,1])
- For a single column pass the bare value: columns='a' or columns=0
- If names and indices must be mixed, read the file (or an index-based subset) first and follow with .select(['a','b'])
- Validate the list before the call: all(isinstance(c, str) ...) or all(isinstance(c, int) ...)
Example fix
# before
df = pl.read_csv("f.csv", columns=[0, "b"]) # TypeError
# after
df = pl.read_csv("f.csv", columns=[0, 1])
# or
df = pl.read_csv("f.csv").select(["a", "b"]) Defensive patterns
Strategy: type-guard
Validate before calling
def check_columns_arg(columns):
if isinstance(columns, (str, int)) and not isinstance(columns, bool):
return
ok = isinstance(columns, (list, tuple)) and len(columns) > 0 and (
all(isinstance(c, str) for c in columns)
or all(isinstance(c, int) and not isinstance(c, bool) for c in columns)
)
if not ok:
raise ValueError(f"columns must be all str or all int, got {columns!r}") Type guard
from typing import TypeGuard
def is_valid_columns_arg(columns: object) -> TypeGuard[list[str] | list[int] | str | int]:
if isinstance(columns, (str, int)) and not isinstance(columns, bool):
return True
return isinstance(columns, (list, tuple)) and len(columns) > 0 and (
all(isinstance(c, str) for c in columns)
or all(isinstance(c, int) and not isinstance(c, bool) for c in columns)
) Try / catch
try:
df = pl.read_csv(path, columns=cols)
except TypeError as e:
if "`columns` argument" in str(e):
raise ValueError(f"invalid columns spec {cols!r}; use all-str or all-int") from e
raise Prevention
- Keep column specs in one vocabulary (names or indices) end-to-end in the pipeline
- Freeze user-supplied column lists to all-str or all-int before calling polars
- Never pass a set, dict, or generator as `columns`
When it happens
Trigger: pl.read_csv('f.csv', columns=[0, 'b']) with mixed int/str entries; columns={'a','b'} (a set, not a list/tuple); columns=[None]; passing a name-to-index dict; same shapes in read_parquet/read_ipc/read_avro which all route through parse_columns_arg.
Common situations: Dynamic column selection where indices and names come from different sources; copying the output of a set comprehension into `columns`; config-driven ETL jobs where the user-supplied column spec is never pre-validated.
Related errors
- `columns` arg should only have unique values, got {columns!r
- cannot specify both `columns` and `read_options["columns"]`
- cannot select columns using key of type {qualified_type_name
- cannot select rows using key of type {qualified_type_name(ke
- cannot treat Series of type {s.dtype} as indices
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/49d5dc31ff2729e7.
Report an issue: GitHub.