pola-rs/polars · error · ValueError

specified column names do not start with 'column_', but auto

Error message

specified column names do not start with 'column_', but autogenerated header names were requested

What it means

In read_csv (py-polars/src/polars/io/csv/functions.py:311-318), when string `columns` is supplied together with has_header=False, the only valid names are the autogenerated 'column_0', 'column_1', ... ones, because no header exists to resolve arbitrary names against. If any requested name does not start with 'column_', the match would silently fail, so polars raises ValueError up front.

Source

Thrown at py-polars/src/polars/io/csv/functions.py:317

    if sample_size != 1024:
        msg = "the `sample_size` parameter was deprecated in 1.10.0, it doesn't do anything anymore"
        issue_deprecation_warning(msg)

    _check_arg_is_1byte("separator", separator, can_be_empty=False)
    _check_arg_is_1byte("quote_char", quote_char, can_be_empty=True)
    _check_arg_is_1byte("eol_char", eol_char, can_be_empty=False)

    projection, columns = parse_columns_arg(columns)
    storage_options = storage_options or {}

    if columns and not has_header:
        for column in columns:
            if not column.startswith("column_"):
                msg = (
                    "specified column names do not start with 'column_',"
                    " but autogenerated header names were requested"
                )
                raise ValueError(msg)

    if schema_overrides is not None and not isinstance(
        schema_overrides, (dict, Sequence)
    ):
        msg = "`schema_overrides` should be of type list or dict"
        raise TypeError(msg)

    if (
        use_pyarrow
        and schema_overrides is None
        and n_rows is None
        and n_threads is None
        and not low_memory
        and null_values is None
    ):
        include_columns: Sequence[str] | None = None
        if columns:
            if not has_header:

View on GitHub (pinned to df599052da)

Solutions

  1. Select by position instead: columns=[0,1] works with has_header=False, then rename the result
  2. Read with autogenerated names and rename: df.rename({'column_0': 'a', ...}) or use new_columns
  3. If the file actually has a header row, remove has_header=False

Example fix

# before
df = pl.read_csv("f.csv", has_header=False, columns=["a", "b"])
# after
df = pl.read_csv("f.csv", has_header=False, columns=[0, 1]).rename({"column_0": "a", "column_1": "b"})
Defensive patterns

Strategy: validation

Validate before calling

def columns_for_headerless(columns) -> list:
    if isinstance(columns, list) and any(
        isinstance(c, str) and not c.startswith("column_") for c in columns
    ):
        raise ValueError(
            "with has_header=False, select by index and rename after reading"
        )
    return columns

Try / catch

try:
    df = pl.read_csv(path, has_header=False, columns=cols)
except ValueError as e:
    if "autogenerated header" in str(e):
        df = pl.read_csv(path, has_header=False).rename(dict(zip(df.columns, cols)))
    else:
        raise

Prevention

When it happens

Trigger: pl.read_csv('f.csv', has_header=False, columns=['a','b']); headerless sensor/log exports where friendly names are requested directly instead of via renaming or projection.

Common situations: Headerless data dumps from instruments/logs where users still want final names immediately; combining has_header=False with name-based selection copied from a headed-file workflow.

Related errors


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