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

  1. Pass raise_if_empty=False and branch on the result: df = pl.read_excel(..., raise_if_empty=False); if df.is_empty(): ...
  2. When iterating all sheets (sheet_id=0), wrap per-sheet reads or skip known-empty tabs
  3. 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 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


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