pola-rs/polars · error · InvalidOperationError

writing {df.height}x{df.width} frame at {position!r} does no

Error message

writing {df.height}x{df.width} frame at {position!r} does not fit worksheet dimensions of {excel_max_valid_rows} rows and {excel_max_valid_cols} columns

What it means

Raised as InvalidOperationError by DataFrame.write_excel when the table (frame dimensions plus its start position and any header/totals rows/columns) extends beyond a worksheet's hard limits: 1,048,575 rows and 16,384 columns (xlsx caps). Polars computes the finish cell from `position`, df.height/width, include_header and column_totals, then rejects the write up front rather than emitting a corrupt file that Excel refuses to open.

Source

Thrown at py-polars/src/polars/dataframe/frame.py:3810

        )
        table_finish = (
            table_start[0]
            + df.height
            + int(is_empty)
            - int(not include_header)
            + int(bool(column_totals)),
            table_start[1] + df.width - 1,
        )

        excel_max_valid_rows = 1048575
        excel_max_valid_cols = 16384

        if (
            table_finish[0] > excel_max_valid_rows
            or table_finish[1] > excel_max_valid_cols
        ):
            msg = f"writing {df.height}x{df.width} frame at {position!r} does not fit worksheet dimensions of {excel_max_valid_rows} rows and {excel_max_valid_cols} columns"
            raise InvalidOperationError(msg)

        # write table structure and formats into the target sheet
        if not is_empty or include_header:
            ws.add_table(
                *table_start,
                *table_finish,
                {
                    "data": df.rows(),
                    "style": table_style,
                    "columns": table_columns,
                    "header_row": include_header,
                    "autofilter": autofilter,
                    "total_row": bool(column_totals) and not is_empty,
                    "name": table_name,
                    **table_options,
                },
            )

View on GitHub (pinned to df599052da)

Solutions

  1. Split the frame across sheets or files: write in chunks of <= ~1M rows with `xlsx.write_frame` on separate worksheets
  2. Start tables at 'A1' / small positions so the position offset doesn't consume the budget
  3. Drop columns or write wide frames transposed; or export to CSV/Parquet when data exceeds Excel's model
  4. Guard before writing: `if df.height > 1_048_575 or df.width > 16_384: ...` route to a different format

Example fix

# before
df.write_excel(workbook='out.xlsx', position='A1040000')

# after
with pl.ExcelWriter('out.xlsx') as xlsx:
    df.write_excel(workbook=xlsx, worksheet='data')
    # large frames: chunk across sheets/rows starting near A1
Defensive patterns

Strategy: validation

Validate before calling

EXCEL_MAX_ROWS, EXCEL_MAX_COLS = 1048575, 16384
start_row, start_col = 1, 1  # from your position; 'A1' == (1, 1)
extra_rows = int(include_header) + int(bool(column_totals))
if start_row + df.height - 1 + extra_rows > EXCEL_MAX_ROWS or start_col + df.width - 1 > EXCEL_MAX_COLS:
    raise ValueError('frame does not fit the target worksheet; chunk or change format')
df.write_excel('out.xlsx', position=position)

Try / catch

try:
    df.write_excel('out.xlsx', position=position)
except pl.exceptions.InvalidOperationError as e:
    if 'does not fit worksheet dimensions' in str(e):
        df.write_csv('out.csv.gz')  # or chunk across sheets
    else:
        raise

Prevention

When it happens

Trigger: Writing a frame with more than ~1,048,575 rows; or a wide frame over 16,384 columns; or a smaller frame placed at a large position like 'XFD1048576' (or a (row, col) tuple near the limits) such that table_finish exceeds the bounds — e.g. a 100k-row frame started at row 1,000,000.

Common situations: Exporting large query results straight to xlsx for analysts; writing multiple frames stacked into one sheet via `position` offsets where an early frame pushes a later one past the boundary; timestamps/IDs pivoted into very wide frames; automated report generation that assumes arbitrary output size.

Related errors


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