Skip to content

The streaming writer must emit a valid ZIP (ZIP64 when large) and reject over-limit row counts ​

Cluster: streaming

Scenario ​

A user streams a very large worksheet to disk with the streaming workbook writer: many rows, each with a wide string cell, committing per row, then the worksheet, then the writer. The resulting .xlsx is structurally corrupted. Excel reports "Repair required", and re-reading it with the library's own streaming reader throws Error: invalid signature: 0x… while walking the ZIP, with the bogus signature value varying by data. A varying signature points at the ZIP container, meaning wrong central-directory or end-of-central-directory offsets, or missing ZIP64 records once the archive or an entry crosses the classic 4 GB / 0xFFFFFFFF offset boundary, not at the spreadsheet XML. It reproduces across every version tried, so it is a long-standing container defect, not a regression.

Spec note, not a corpus case: the defect only manifests once the streamed output crosses a ZIP64 size or offset boundary, and the reporter used ten million rows, which is far too large to write in CI without OOM or timeout. A hostile-or-huge repro belongs in a spec note; a corpus case would stall the runner. Moderate streamed workbooks already produce valid, re-readable ZIPs, locked by streaming-writer-produces-valid-zip-package, so the assertable target here is the large-scale container correctness, verified by design review and a bounded large-ish smoke test off the CI path.

Desired behavior ​

  • The streamed archive is always a structurally valid ZIP. Its central directory and end-of-central-directory records point at correct entry offsets, so any conformant ZIP reader walks every entry without hitting an invalid local-file-header signature, regardless of how large the streamed content grows.
  • ZIP64 is emitted when needed. Once the archive, an entry's compressed or uncompressed size, an entry offset, or the entry count crosses the classic 32-bit limits, the writer emits the ZIP64 end-of-central-directory record and locator and the per-entry ZIP64 extra fields, so offsets and sizes beyond 0xFFFFFFFF are represented correctly rather than truncated into a bogus offset.
  • A large streamed workbook is re-readable by the streaming reader: iterating its worksheets succeeds and yields the written rows, not an invalid-signature error.
  • Over-limit row counts fail loudly at write time. When the requested rows exceed the format maximum of 1,048,576 per worksheet, the writer raises a clear, typed error when the limit is crossed rather than silently emitting a corrupt file. This is a distinct guard from the ZIP64 fix: even a valid ZIP holding an over-tall sheet is not a valid spreadsheet.

Open questions ​

  • Whether the underlying zip layer, today's dependency or the planned lean-zip rewrite, emits ZIP64 correctly, or whether ZIP64 support is the actual gap. This ties directly to lean-zip-container-strategy.
  • What a meaningful large-ish smoke test looks like: big enough to exercise the beyond-4 GB and beyond-0xFFFFFFFF offset path, or at least the entry-count and streaming-CRC paths, without OOM or timeout on CI, possibly gated behind an opt-in "slow" tag rather than the default corpus run.
  • Whether to expose a streaming-time progress or size signal so a caller can detect approaching limits, and how the row-count guard interacts with multi-sheet streamed workbooks.

Related: streaming-writer-produces-valid-zip-package, lean-zip-container-strategy, bounded-recursion-no-stack-overflow, streaming-write-memory-and-shared-strings-tradeoff.

Released under the MIT License.