pola-rs/polars · error · NoDataError
empty Excel sheet If you want to read this as an empty Data
Error message
empty Excel sheet If you want to read this as an empty DataFrame, set `raise_if_empty=False`.
What it means
Raised as polars.exceptions.NoDataError by _empty_frame whenever the selected sheet turns out to contain no data and raise_if_empty is True (the default). It is reached from all three engines: a zero-byte CSV buffer in the xlsx2csv path, an empty used-range in openpyxl, or an all-null frame in calamine after _drop_null_data. The message itself tells you the escape hatch: pass raise_if_empty=False to get an empty DataFrame instead.
Source
Thrown at py-polars/src/polars/io/spreadsheet/functions.py:1010
):
null_cols.append(col_name)
if null_cols:
df = df.drop(*null_cols)
if df.height == df.width == 0:
return _empty_frame(raise_if_empty)
if drop_empty_rows:
return df.filter(~F.all_horizontal(F.all().is_null()))
return df
def _empty_frame(raise_if_empty: bool) -> pl.DataFrame: # noqa: FBT001
if raise_if_empty:
msg = (
"empty Excel sheet"
"\n\nIf you want to read this as an empty DataFrame, set `raise_if_empty=False`."
)
raise NoDataError(msg)
return pl.DataFrame()
def _reorder_columns(
df: pl.DataFrame, columns: Sequence[int] | Sequence[str] | None
) -> pl.DataFrame:
if columns:
from polars.selectors import by_index, by_name
cols = (
by_index(*columns)
if is_non_empty_sequence_of(columns, int)
else by_name(*columns)
)
df = df.select(cols)
return df
View on GitHub (pinned to df599052da)
Solutions
- Pass raise_if_empty=False and branch on the result: df = pl.read_excel(..., raise_if_empty=False); if df.is_empty(): ...
- When iterating all sheets (sheet_id=0), wrap per-sheet reads or skip known-empty tabs
- Verify you selected the intended sheet — an empty result often means the wrong tab was addressed
Example fix
# before
df = pl.read_excel(src, sheet_name='Notes') # blank sheet -> NoDataError
# after
df = pl.read_excel(src, sheet_name='Notes', raise_if_empty=False)
if df.is_empty():
df = pl.DataFrame() # or skip / log this sheet Defensive patterns
Strategy: try-catch
Validate before calling
# cheapest pre-check without a full parse: use raise_if_empty=False and inspect
frame = pl.read_excel(src, sheet_name='Notes', raise_if_empty=False)
if frame.is_empty():
handle_empty('Notes') # skip / default frame / log Try / catch
from polars.exceptions import NoDataError
try:
df = pl.read_excel(src, sheet_name=name)
except NoDataError:
df = pl.DataFrame() # empty sheet is an expected domain state
# or, when looping all sheets:
frames = {}
for name in sheet_names(src):
try:
frames[name] = pl.read_excel(src, sheet_name=name)
except NoDataError:
continue Prevention
- When blank tabs are possible (templates, notes sheets), pass raise_if_empty=False and branch on df.is_empty()
- For sheet_id=0 bulk reads, expect NoDataError per sheet instead of one monolithic call
- Import NoDataError from polars.exceptions — it is a PolarsError, not a ValueError
When it happens
Trigger: pl.read_excel(src, sheet_name='Notes') on a blank-but-present sheet; reading with sheet_id=0 where some tabs are empty (first empty tab aborts everything); header-only sheets that drop_empty_rows filters to zero rows; formatted-but-dataless sheets.
Common situations: Heterogeneous workbooks where documentation/template tabs are empty; scheduled jobs over user-supplied files where a blank tab is normal; sheets whose only content is styling or a pivot cache.
Related errors
- cannot describe a DataFrame that has no columns
- empty data from {context}{hint}
- no data found in the given workbook(s) and sheet(s)
- cannot specify both `columns` and `read_options["columns"]`
- the values of `has_header` and `read_options["has_header"]`
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/9c1968aad0f3859b.
Report an issue: GitHub.