Fix
Getting Started With Python Excel AutomationDeep dive

Fix "Filesize would require ZIP64 extensions" (LargeZipFile) in XlsxWriter

Very large exports fail at close() with xlsxwriter.exceptions.FileSizeError: Filesize would require ZIP64 extensions, raised from zipfile.LargeZipFile. Learn what crosses the limit (one XML part over 2 GiB, not the .xlsx file size), estimate when your export will hit it, turn on use_zip64 in XlsxWriter or through pandas, and when to split the data or choose another format instead.

A nightly export that has run for months suddenly fails at the very end — after minutes of writing — with:

Text
xlsxwriter.exceptions.FileSizeError: Filesize would require ZIP64 extensions. Use workbook.use_zip64().

Older XlsxWriter versions, and code that catches the lower-level exception, show zipfile.LargeZipFile: File size too large instead. The message mentions file size, but the finished .xlsx may be only a few hundred megabytes. What crossed the limit is one XML part inside the package, before compression. This page explains the limit, shows how to predict when an export will hit it, and covers the one-line fix and the cases where the better fix is a smaller workbook. It belongs to Troubleshooting Common Python Excel Errors.

Prerequisites

Bash
pip install xlsxwriter pandas

Reproducing the error for real means writing more than two gigabytes of XML, which takes minutes and a lot of disk. The examples below lower Python's zipfile threshold for the duration of a test, so the same code path raises the same exception on a small workbook.

Step 1 — Understand what the limit applies to

An .xlsx file is a ZIP archive, and each worksheet is one member of it: xl/worksheets/sheet1.xml. The original ZIP format records sizes in 32-bit fields; members larger than that need the ZIP64 extension. Python's zipfile refuses to write ZIP64 unless the caller allows it, and its threshold is zipfile.ZIP64_LIMIT:

Python
import zipfile

print(f"{zipfile.ZIP64_LIMIT:,} bytes = {zipfile.ZIP64_LIMIT / 2**30:.2f} GiB")

The limit is 2,147,483,647 bytes — 2 GiB — per member, uncompressed. XlsxWriter writes each sheet's XML to a temporary file first and adds it to the archive when you call close(), which is why the error appears at the very end. Sheet XML compresses about four to one, so a workbook can fail with a 2 GiB sheet part while the final .xlsx would have been around 500 MB.

Where the 2 GiB limit applies The .xlsx archive contains XML parts. The limit applies to each part's uncompressed size, so sheet1.xml at 2.3 GiB triggers the error even though the compressed workbook would be about 600 MB. report.xlsx on disk ≈ 600 MB compressed — not the problem xl/worksheets/sheet1.xml 2.3 GiB uncompressed — over the limit zipfile.ZIP64_LIMIT 2,147,483,647 bytes per member

Step 2 — Reproduce it on a small workbook

Python
import xlsxwriter
from xlsxwriter.exceptions import FileSizeError

def write_rows(path, rows, **options):
    wb = xlsxwriter.Workbook(path, options)
    ws = wb.add_worksheet()
    for r in range(rows):
        ws.write_row(r, 0, [r, r * 1.5, f"item {r % 50}"])
    wb.close()

real_limit = zipfile.ZIP64_LIMIT
zipfile.ZIP64_LIMIT = 50_000            # pretend the limit is 50 KB
try:
    write_rows("export.xlsx", 5_000)
except FileSizeError as exc:
    print("FileSizeError:", exc)
    print("caused by:", type(exc.__context__).__name__)
finally:
    zipfile.ZIP64_LIMIT = real_limit

The sheet's XML for 5,000 rows is well over 50 KB, so close() raises exactly the production error, with zipfile.LargeZipFile as the underlying cause. Restoring the real limit in finally matters — the constant is global for the whole process.

Step 3 — Turn on ZIP64

XlsxWriter allows ZIP64 through a constructor option or a method; either must be set before close():

Python
zipfile.ZIP64_LIMIT = 50_000
try:
    write_rows("export_zip64.xlsx", 5_000, use_zip64=True)
    print("written with ZIP64")
finally:
    zipfile.ZIP64_LIMIT = real_limit

from openpyxl import load_workbook
print("rows read back:", load_workbook("export_zip64.xlsx", read_only=True).active.max_row)

Workbook(path, {"use_zip64": True}) and calling workbook.use_zip64() after creating the workbook are equivalent. The output is a valid ZIP64 package; current Excel versions, LibreOffice, openpyxl and pandas read it. XlsxWriter keeps ZIP64 off by default because some older ZIP readers do not understand the extension, so enable it for the exports that need it rather than everywhere, and open one such file in the oldest Excel your recipients use before relying on it.

From pandas, pass the option through engine_kwargs:

Python
import pandas as pd

df = pd.DataFrame({"id": range(5_000), "value": [i * 1.5 for i in range(5_000)]})
zipfile.ZIP64_LIMIT = 50_000
try:
    with pd.ExcelWriter("pandas_zip64.xlsx", engine="xlsxwriter",
                        engine_kwargs={"options": {"use_zip64": True}}) as xw:
        df.to_excel(xw, index=False)
    print("pandas export written")
finally:
    zipfile.ZIP64_LIMIT = real_limit

Step 4 — Predict when an export will hit the limit

Measure how many bytes of XML one cell of your data produces, then extrapolate. A sample of 20,000 rows is enough:

Python
import random

random.seed(0)
sample_rows, cols = 20_000, 20
wb = xlsxwriter.Workbook("sample.xlsx", {"constant_memory": True})
ws = wb.add_worksheet()
for r in range(sample_rows):
    ws.write_row(r, 0, [random.random() * 10_000 for _ in range(15)] + [f"cat{random.randint(1, 50)}" for _ in range(5)])
wb.close()
part = zipfile.ZipFile("sample.xlsx").getinfo("xl/worksheets/sheet1.xml")
per_cell = part.file_size / (sample_rows * cols)
print(f"{per_cell:.1f} bytes per cell; compressed {part.file_size / part.compress_size:.1f}:1")
print(f"cells per sheet before the limit: {real_limit / per_cell:,.0f}")
print(f"columns that fit in 1,048,576 rows: {real_limit / per_cell / 1_048_576:.0f}")

With this mix of decimals and short text, each cell costs about 45 bytes of XML, so a sheet reaches 2 GiB at roughly 48 million cells — a full-height sheet of 1,048,576 rows with around 45 columns. Long text, many-digit floats and cell formats push the number per cell up; small integers push it down. Run the estimate on a sample of your real data before the export grows into the limit.

Rough cell counts that reach 2 GiB of sheet XML Estimated cells per sheet before the 2 GiB limit, by average XML bytes per cell. At 30 bytes per cell about 72 million cells fit, at 45 bytes about 48 million, and at 80 bytes about 27 million. 30 bytes / cell (small ints) ≈ 72 M cells 45 bytes / cell (measured mix) ≈ 48 M cells 80 bytes / cell (long text) ≈ 27 M cells A full sheet is 1,048,576 rows, so 48 M cells is about 45 columns at full height.

Step 5 — Consider a smaller workbook instead

Turning on ZIP64 makes the file writable; it does not make it usable. A worksheet with tens of millions of cells opens slowly, strains Excel's memory and is close to the sheet's row limit anyway. Often the better fix is structural:

Turn on ZIP64 or reshape the export? If people will open the workbook in Excel, split or summarise it so each sheet stays small. If a program consumes it and must be xlsx, enable use_zip64. If the consumer can accept another format, write Parquet or CSV. Who uses the export? people in Excel Split or summarise smaller sheets open faster a program needing xlsx use_zip64 one option, valid ZIP64 a program Parquet or CSV no size ceiling worth worrying about

Step 6 — Decide before writing, not after

The worst property of this error is its timing: it arrives after the whole export has been generated. A pre-flight check using the bytes-per-cell estimate from Step 4 lets the job choose ZIP64 — or a split — before it starts:

Python
def needs_zip64(n_rows, n_cols, bytes_per_cell=per_cell, margin=1.25):
    return n_rows * n_cols * bytes_per_cell * margin > real_limit

for rows, cols in [(500_000, 20), (1_048_576, 30), (1_048_576, 60)]:
    print(f"{rows:>9,} x {cols:>2} -> use_zip64={needs_zip64(rows, cols)}")

The 25% margin covers the variation between your sample and the full data. Feeding the result straight into the workbook options — xlsxwriter.Workbook(path, {"use_zip64": needs_zip64(len(df), df.shape[1])}) — keeps small exports on the most compatible format and turns ZIP64 on only for the large ones. Log the decision, so that a recipient who reports a problem opening the file can be matched to the exports that used the extension.

Performance notes

Exports of this size are where XlsxWriter's constant_memory option earns its keep: rows are flushed to the temporary file as they are written, so memory stays flat instead of growing with the sheet. It requires writing rows in order, top to bottom. The ZIP64 option itself costs nothing measurable. The time goes into generating and compressing gigabytes of XML — expect several minutes for a sheet near the limit — which is one more argument for splitting very large exports or moving them to Parquet.

Common pitfalls

  • Judging by the final file size. The limit is on the uncompressed sheet XML, roughly four times the size of the compressed workbook.
  • Setting the option too late. use_zip64 must be set before close(), and for pandas before the writer closes.
  • Leaving a patched limit in place. If you lower zipfile.ZIP64_LIMIT in a test, restore it in finally.
  • Shared strings. Huge amounts of unique text can push sharedStrings.xml over the limit instead of the sheet; the same option fixes it.
  • Hitting the row limit next. 1,048,576 rows per sheet still applies; see Fix "This sheet is too large" Error.

Conclusion

FileSizeError: Filesize would require ZIP64 extensions (or zipfile.LargeZipFile) means one XML part of the workbook exceeds 2 GiB uncompressed — typically a sheet with tens of millions of cells. Enable ZIP64 with Workbook(path, {"use_zip64": True}) or, from pandas, engine_kwargs={"options": {"use_zip64": True}}. Estimate bytes per cell on a sample to see the limit coming, and when people will open the file, prefer splitting or summarising over a single enormous sheet.

Frequently asked questions

What does "Filesize would require ZIP64 extensions" mean in XlsxWriter? One part of the .xlsx package, usually a worksheet's XML, is larger than 2 GiB before compression. Python's zipfile needs the ZIP64 extension for that, and XlsxWriter only allows it when you enable use_zip64.

How do I enable ZIP64 in XlsxWriter? Pass {"use_zip64": True} as the options argument of xlsxwriter.Workbook, or call workbook.use_zip64() before closing the workbook.

How do I fix LargeZipFile when writing Excel with pandas? Use the xlsxwriter engine and pass engine_kwargs={"options": {"use_zip64": True}} to pd.ExcelWriter, then write the DataFrame as usual.

My .xlsx would be 500 MB — why does it hit a 2 GB limit? The limit applies to each XML part before compression. Sheet XML compresses roughly four to one, so a 2 GiB sheet part becomes a workbook of around 500 MB.

More on errors & fixes

More on errors & fixes →