pola-rs/polars · error · ValueError
cannot specify both `sheet_name` ({sheet_name!r}) and `sheet
Error message
cannot specify both `sheet_name` ({sheet_name!r}) and `sheet_id` ({sheet_id!r}) What it means
Raised by polars.read_excel and pl.read_ods in _get_sheet_names (a ValueError) when both sheet_id and sheet_name are not None. Sheet selection is mutually exclusive by design: id-based and name-based selection cannot be combined, even when they point at the same sheet. This check runs before any worksheet data is parsed.
Source
Thrown at py-polars/src/polars/io/spreadsheet/functions.py:789
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 df599052da)
Solutions
- Pass exactly one of sheet_id or sheet_name; explicitly set the other to None
- In wrapper functions, resolve the config to a single selector before calling read_excel
- Remember sheet_id is 1-based and 0 means 'all sheets' when choosing which side to keep
Example fix
# before
pl.read_excel('f.xlsx', sheet_id=1, sheet_name='Sheet1')
# after
pl.read_excel('f.xlsx', sheet_name='Sheet1') Defensive patterns
Strategy: validation
Validate before calling
def resolve_sheet_selector(sheet_id, sheet_name):
if sheet_id is not None and sheet_name is not None:
raise ValueError('pass either sheet_id or sheet_name, not both')
return sheet_id, sheet_name
sheet_id, sheet_name = resolve_sheet_selector(sheet_id, sheet_name)
df = pl.read_excel(src, sheet_id=sheet_id, sheet_name=sheet_name) Try / catch
try:
df = pl.read_excel(src, sheet_id=sheet_id, sheet_name=sheet_name)
except ValueError as e:
if 'cannot specify both' in str(e):
df = pl.read_excel(src, sheet_name=sheet_name) # keep one selector
else:
raise Prevention
- Resolve config down to exactly one of sheet_id / sheet_name before calling read_excel/read_ods
- Remember sheet_id is 1-based and 0 means 'all sheets'
- In **kwargs-based wrappers, drop whichever selector is None instead of passing both
When it happens
Trigger: pl.read_excel('f.xlsx', sheet_id=1, sheet_name='Sheet1'); pl.read_ods('f.ods', sheet_id=[1,2], sheet_name='data'); also fires when wrapper code computes both values from defaults and ends up passing neither as None.
Common situations: Config-driven loaders where sheet_id and sheet_name are both populated 'to be safe'; refactoring code from name-based to position-based selection while forgetting to remove the old argument; passing **kwargs dictionaries that carry both keys.
Related errors
- no matching sheet found when `sheet_name` is {name!r}
- no matching sheet found when `sheet_id` is {idx}
- a more recent version of `fastexcel` is required for 'schema
- table named {table_name!r} not found in sheet {sheet_name!r}
- cannot set both `with_column_names` and `new_columns`; mutua
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/fd22504dc489e1fd.
Report an issue: GitHub.