pola-rs/polars · error · ValueError
cannot specify both `sheet_name
Error message
cannot specify both `sheet_name` ({sheet_name!r}) and `sheet_id` ({sheet_id!r}) What it means
`read_excel` allows selecting sheets either by index (`sheet_id`) or by name (`sheet_name`), but not both at once, since the selections could disagree. `_get_sheet_names` raises a `ValueError` when both are non-None.
Solutions
- Pass only `sheet_id` OR only `sheet_name`
- Set one of them explicitly to None
- If multiple selections are needed, pass a list to a single parameter (both accept lists)
Example fix
// before pl.read_excel(f, sheet_id=1, sheet_name='Sales') // after pl.read_excel(f, sheet_name='Sales')
Defensive patterns
Strategy: validation
Validate before calling
assert sheet_id is None or sheet_name is None, 'pass sheet_id or sheet_name, not both'
Try / catch
try:
df = pl.read_excel(f, sheet_id=sid, sheet_name=sname)
except ValueError as e:
if 'cannot specify both' in str(e):
df = pl.read_excel(f, sheet_name=sname)
else:
raise Prevention
- Default both to None in wrappers, never to sentinel values
- Choose one sheet-selection convention per codebase
- Use lists on a single parameter for multi-sheet reads
When it happens
Trigger: `pl.read_excel(f, sheet_id=1, sheet_name='Sales')` or passing a non-default value for both parameters in any combination (ints, strings, or lists).
Common situations: Combining defaults from a wrapper function where each parameter defaults to a sentinel that became non-None; copy-pasted calls that accumulate parameters.
Related errors
- cannot specify both `columns` and `read_options["columns"]`
- cannot specify both `columns` and…
- cannot specify both `infer_schema_length` and…
- file must be opened in binary mode
- no matching sheet found when `sheet_id` is
AI-assisted analysis of pola-rs/polars@fe841f959e (2026-09-18).
Data as JSON: /api/errors/fd22504dc489e1fd.
Report an issue: GitHub.
Appendix: source
Thrown at py-polars/src/polars/io/spreadsheet/functions.py:794
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."""
if sheet_id is not None and sheet_name is not None:
msg = f"cannot specify both `sheet_name` ({sheet_name!r}) and `sheet_id` ({sheet_id!r})"
raise ValueError(msg)
sheet_names = []
if sheet_id is None and sheet_name is None:
name = None if table_name else worksheets[0]["name"]
sheet_names.append(name)
return_multiple_sheets = False
elif sheet_id == 0:
sheet_names.extend(ws["name"] for ws in worksheets)
return_multiple_sheets = True
else:
return_multiple_sheets = (
(isinstance(sheet_name, Sequence) and not isinstance(sheet_name, str))
or isinstance(sheet_id, Sequence)
or sheet_id == 0
)
if names := (
(sheet_name,) if isinstance(sheet_name, str) else sheet_name or ()
):View on GitHub (pinned to fe841f959e)