pola-rs/polars · error · ParameterCollisionError

cannot specify both `infer_schema_length` and `read_options[

Error message

cannot specify both `infer_schema_length` and `read_options["infer_schema_length"]`

What it means

Raised by polars.read_excel (engine='xlsx2csv') in _get_read_options when 'infer_schema_length' is a key in read_options AND the top-level infer_schema_length differs from the polars default (N_INFER_DEFAULT = 100). It only fires when you explicitly changed the top-level value (including to None) and also put the key in read_options; otherwise the top-level value silently overwrites read_options after the check. The key is forwarded to the internal read_csv call used by the xlsx2csv engine.

Source

Thrown at py-polars/src/polars/io/spreadsheet/functions.py:768

        read_options["schema_sample_rows"] = infer_schema_length
        if has_header is False and "header_row" not in read_options:
            read_options["header_row"] = None

    elif engine == "xlsx2csv":
        if ("columns" in read_options) and columns:
            msg = 'cannot specify both `columns` and `read_options["columns"]`'
            raise ParameterCollisionError(msg)
        elif (
            "has_header" in read_options
            and read_options["has_header"] is not has_header
        ):
            msg = 'the values of `has_header` and `read_options["has_header"]` are not compatible'
            raise ParameterCollisionError(msg)
        elif ("infer_schema_length" in read_options) and (
            infer_schema_length != N_INFER_DEFAULT
        ):
            msg = 'cannot specify both `infer_schema_length` and `read_options["infer_schema_length"]`'
            raise ParameterCollisionError(msg)

        read_options["infer_schema_length"] = infer_schema_length
        if "has_header" not in read_options:
            read_options["has_header"] = has_header
    else:
        read_options["infer_schema_length"] = infer_schema_length
        read_options["has_header"] = has_header

    return read_options


def _get_sheet_names(
    sheet_id: int | Sequence[int] | None,
    sheet_name: str | Sequence[str] | None,
    table_name: str | None,
    worksheets: list[dict[str, Any]],
) -> tuple[list[str], bool]:
    """Establish sheets to read; indicate if we are returning a dict frames."""

View on GitHub (pinned to df599052da)

Solutions

  1. Keep infer_schema_length only as the top-level parameter and remove the key from read_options
  2. If you genuinely need the csv-level key, leave the top-level parameter at its default (do not set it)
  3. Prefer read_options only for csv-specific keys (separator, truncate_ragged_lines, schema_overrides, etc.)

Example fix

# before
pl.read_excel(src, engine='xlsx2csv', infer_schema_length=None, read_options={'infer_schema_length': None, 'skip_rows': 2})

# after
pl.read_excel(src, engine='xlsx2csv', infer_schema_length=None, read_options={'skip_rows': 2})
Defensive patterns

Strategy: validation

Validate before calling

opts = dict(read_options or {})
if 'infer_schema_length' in opts:
    del opts['infer_schema_length']  # single source of truth: the top-level parameter
df = pl.read_excel(src, engine='xlsx2csv', infer_schema_length=infer_schema_length, read_options=opts)

Try / catch

from polars.exceptions import ParameterCollisionError
try:
    df = pl.read_excel(src, engine='xlsx2csv', infer_schema_length=isl, read_options=opts)
except ParameterCollisionError as e:
    if 'infer_schema_length' in str(e):
        isl = opts.pop('infer_schema_length')
        df = pl.read_excel(src, engine='xlsx2csv', infer_schema_length=isl, read_options=opts)
    else:
        raise

Prevention

When it happens

Trigger: pl.read_excel(src, engine='xlsx2csv', infer_schema_length=None, read_options={'infer_schema_length': 500}) or infer_schema_length=1000 with the key also present in read_options.

Common situations: Tuning schema inference in two places because old examples put 'infer_schema_length' inside csv-style read_options; teams adding read_options wholesale from a shared config dict that already carries the key.

Related errors


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